HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
controllerBuilder.h
Go to the documentation of this file.
1 //
2 // Copyright 2026 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_EXEC_EXEC_IR_CONTROLLER_BUILDER_H
8 #define PXR_EXEC_EXEC_IR_CONTROLLER_BUILDER_H
9 
10 /// \file
11 ///
12 /// Registration utilities for defining invertible controller computations,
13 /// which are the basis for invertible rigging.
14 ///
15 /// Controllers define forward computations that take the values of input
16 /// attributes and produce output values. Controllers also define inverse
17 /// computations that take desired values for outputs and produce the input
18 /// values necessary for the forward computation to produce the desired results.
19 ///
20 
21 #include "pxr/pxr.h"
22 
23 #include "pxr/exec/execIr/tokens.h"
24 #include "pxr/exec/execIr/types.h"
25 
29 
31 
32 /// Builder class used to register invertible controller computations.
33 ///
34 /// This class can only be used in the context of schema computation
35 /// registration. The constructor takes the `self` builder object that is
36 /// defined by the `EXEC_REGISTER_COMPUTATIONS_FOR_SCHEMA` macro. The
37 /// constructor also takes the callbacks that implement the forward and inverse
38 /// computations for the controller. The client uses member functions to
39 /// register controller atributes as inputs, outputs, switches, etc. (see the
40 /// documentation on the corresonding registration methods for details). These
41 /// registrations, in turn, generate the computation inputs for the callbacks
42 /// (as documented in the class function documentation), as well as other
43 /// computations that are required to implement invertible controllers within
44 /// OpenExec.
45 ///
46 /// # Example
47 ///
48 /// ```cpp
49 ///
50 /// // Forward declare forward and inverse functions.
51 /// static ExecIrResult _ForwardCompute(const VdfContext &ctx);
52 /// static ExecIrResult _InverseCompute(const VdfContext &ctx);
53 ///
54 /// EXEC_REGISTER_COMPUTATIONS_FOR_SCHEMA(MyAddOneController)
55 /// {
56 /// auto builder = ExecIrControllerBuilder(
57 /// self, _ForwardCompute, _InverseCompute);
58 ///
59 /// // Register one invertible input and one invertible output.
60 /// builder.InvertibleInputAttribute(_tokens->input);
61 /// builder.InvertibleOutputAttribute(_tokens->output);
62 /// }
63 ///
64 /// // The forward compute callback function.
65 /// //
66 /// // The VdfContext provides values for all inputs. The function is
67 /// // responsible for computing all output values, returning the values in a
68 /// // map from output name to VtValue.
69 /// //
70 /// static ExecIrResult
71 /// _ForwardCompute(const VdfContext & ctx)
72 /// {
73 /// // Extract the input value.
74 /// const double input = ctx.GetInputValue<double>(_tokens->input);
75 ///
76 /// // Create a map to store the results.
77 /// ExecIrResult result;
78 ///
79 /// // Compute and store the output value.
80 /// result[_tokens->output] = input + 1.0;
81 ///
82 /// return result;
83 /// }
84 ///
85 /// // The inverse compute callback function.
86 /// //
87 /// // The context provides desired values for all invertible outputs. The
88 /// // function is responsible for computing the invertible input values that
89 /// // satisfy the desired output values, returning the values in a map from
90 /// // invertible input name to VtValue.
91 /// //
92 /// static ExecIrResult
93 /// _InverseCompute(const VdfContext & ctx)
94 /// {
95 /// // Extract the output value.
96 /// const double output = ctx.GetInputValue<double>(_tokens->output);
97 ///
98 /// // Create a map to store the results
99 /// ExecIrResult result;
100 ///
101 /// // Compute and store the input value
102 /// result[_tokens->input] = output - 1.0;
103 ///
104 /// return result;
105 /// }
106 /// ```
107 ///
109 public:
110 
111  /// The type for forward and inverse controller computation calbacks.
112  using Callback = ExecIrResult(*)(const VdfContext &);
113 
114  /// Constructs a builder that is used to register computations that
115  /// implement an invertible controller.
116  ///
117  /// \p self is the builder that is defined by
118  /// `EXEC_REGISTER_COMPUTATIONS_FOR_SCHEMA`. \p forwardCallback and \p
119  /// inverseCallback are the callbacks that define the forward and inverse
120  /// computations that implement the controller to be registered by the
121  /// constructed instance.
122  ///
123  EXECIR_API
126  Callback forwardCallback,
127  Callback inverseCallback);
128 
129  /// Registers an invertible input attribute.
130  ///
131  /// - Invertible input attributes provide input to the forward computation.
132  /// - Invertible input values are produced by the inverse computation.
133  ///
134  template <typename ValueType>
135  void
137  const TfToken &attributeName);
138 
139  /// Registers a non-invertible input attribute.
140  ///
141  /// - All input attributes provide input to the forward computation.
142  /// - Non-invertible input attributes also provide input to the inverse
143  /// computation.
144  ///
145  template <typename ValueType>
146  void
148  const TfToken &attributeName);
149 
150  /// Registers an invertible output attribute; the output is inverible if \p
151  /// invertible is `true`.
152  ///
153  /// - Output attributes produce computed values that are the results of the
154  /// forward computation and provide input to the inverse computation.
155  ///
156  /// TODO: Non-invertible output attributes are not yet implemented.
157  ///
158  template <typename ValueType>
159  void
161  const TfToken &attributeName);
162 
163  /// Registers a switch attribute.
164  ///
165  /// Switch attributes hold values that change the behavior of the forward
166  /// and inverse computations.
167  ///
168  /// - Switch attributes provide input to both the forward and the inverse
169  /// computation.
170  ///
171  template <typename ValueType>
172  void
174  const TfToken &attributeName);
175 
176  /// Registers a passthrough attribute.
177  ///
178  /// - Passthrough attributes provide input to both the forward and the
179  /// inverse computation.
180  ///
181  template <typename ValueType>
182  void
184  const TfToken &attributeName);
185 
186 private:
187  // Returns a private token used to name constant inputs.
188  EXECIR_API
189  static const TfToken &_GetConstantInputName();
190 
191 private:
192  ExecComputationBuilder &_self;
193  ExecPrimComputationBuilder _forwardComputeReg;
194  ExecPrimComputationBuilder _inverseComputeReg;
195 };
196 
197 template <typename ValueType>
198 void
200  const TfToken &attributeName)
201 {
202  using namespace exec_registration;
203 
204  // All input attributes (invertible or not) are inputs to the forward
205  // computation.
206  _forwardComputeReg.Inputs(AttributeValue<ValueType>(attributeName));
207 }
208 
209 template <typename ValueType>
210 void
212  const TfToken &attributeName)
213 {
214  using namespace exec_registration;
215 
216  // All input attributes (invertible or not) are inputs to the forward
217  // computation.
218  _forwardComputeReg.Inputs(AttributeValue<ValueType>(attributeName));
219 
220  // Non-invertible input attributes are inputs to the inverse computation.
221  _inverseComputeReg.Inputs(AttributeValue<ValueType>(attributeName));
222 }
223 
224 template <typename ValueType>
225 void
227  const TfToken &attributeName)
228 {
229  using namespace exec_registration;
230 
231  // All outputs (invertible or not) are inputs to the inverse computation.
232  //
233  // TODO: We pull on the resolved value because otherwise, for invertible
234  // outputs, we get the computed value from the forward computation. But what
235  // we really want here is the "desired value," i.e., the value the inversion
236  // is trying to satisfy. For now, we use the authored value as the way the
237  // desired value is specified.
238  _inverseComputeReg.Inputs(
239  Attribute(attributeName)
240  .Computation<ValueType>(ExecBuiltinComputations->computeResolvedValue)
241  .InputName(attributeName));
242 
243  // Register an expression on the invertible output that pulls its value
244  // from the forward computation result map.
245  _self.AttributeExpression(attributeName)
246  .Callback(+[](const VdfContext &ctx) -> ValueType {
247  const TfToken &attributeName =
248  ctx.GetInputValue<TfToken>(_GetConstantInputName());
249  const ExecIrResult &resultMap =
250  ctx.GetInputValue<ExecIrResult>(ExecIrTokens->forwardCompute);
251  const auto it = resultMap.find(attributeName);
252  if (it != resultMap.end()) {
253  return it->second.Get<ValueType>();
254  }
255 
257  "Failed to find a result value for output attribute '%s' "
258  "when computing %s",
259  attributeName.GetText(),
260  ctx.GetNodeDebugName().c_str());
263  })
264  .Inputs(
265  Prim().Computation<ExecIrResult>(ExecIrTokens->forwardCompute),
266  Constant(attributeName).InputName(_GetConstantInputName()));
267 }
268 
269 template <typename ValueType>
270 void
272  const TfToken &attributeName)
273 {
274  using namespace exec_registration;
275 
276  // Switch attributes are inputs to the forward and inverse computations.
277  _forwardComputeReg.Inputs(AttributeValue<ValueType>(attributeName));
278  _inverseComputeReg.Inputs(AttributeValue<ValueType>(attributeName));
279 }
280 
281 template <typename ValueType>
282 void
284  const TfToken &attributeName)
285 {
286  using namespace exec_registration;
287 
288  // Passthrough attributes are inputs to the forward and inverse
289  // computations.
290  _forwardComputeReg.Inputs(AttributeValue<ValueType>(attributeName));
291  _inverseComputeReg.Inputs(AttributeValue<ValueType>(attributeName));
292 }
293 
295 
296 #endif
Class used to build prim computation definitions.
void InvertibleInputAttribute(const TfToken &attributeName)
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
#define TF_CODING_ERROR
void NonInvertibleInputAttribute(const TfToken &attributeName)
#define EXECIR_API
Definition: api.h:25
TfDenseHashMap< TfToken, VtValue, TfToken::HashFunctor > ExecIrResult
Definition: types.h:25
VdfByValueOrConstRef< T > GetInputValue(const TfToken &name) const
Definition: context.h:300
Definition: token.h:70
ExecIrResult(*)(const VdfContext &) Callback
The type for forward and inverse controller computation calbacks.
void SwitchAttribute(const TfToken &attributeName)
iterator find(const key_type &k)
Definition: denseHashMap.h:368
EXEC_API TfStaticData< Exec_BuiltinComputationTokens > ExecBuiltinComputations
EXECIR_API ExecIrControllerBuilder(ExecComputationBuilder &self, Callback forwardCallback, Callback inverseCallback)
iterator end()
Definition: denseHashMap.h:350
char const * GetText() const
Definition: token.h:179
static VDF_API VdfExecutionTypeRegistry & GetInstance()
Computation value specifier, valid for providing input to any computation.
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
VDF_API std::string GetNodeDebugName() const
bool ValueType
Definition: NanoVDB.h:5729
void InvertibleOutputAttribute(const TfToken &attributeName)
void PassthroughAttribute(const TfToken &attributeName)