1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef USDGEOM_GENERATED_XFORMABLE_H
25 #define USDGEOM_GENERATED_XFORMABLE_H
26 
27 /// \file usdGeom/xformable.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/usdGeom/api.h"
31 #include "pxr/usd/usdGeom/imageable.h"
32 #include "pxr/usd/usd/prim.h"
33 #include "pxr/usd/usd/stage.h"
34 #include "pxr/usd/usdGeom/tokens.h"
35 
36 #include "pxr/usd/usdGeom/xformOp.h"
37 #include <vector>
38 
39 #include "pxr/base/vt/value.h"
40 
41 #include "pxr/base/gf/vec3d.h"
42 #include "pxr/base/gf/vec3f.h"
43 #include "pxr/base/gf/matrix4d.h"
44 
45 #include "pxr/base/tf/token.h"
46 #include "pxr/base/tf/type.h"
47 
48 PXR_NAMESPACE_OPEN_SCOPE
49 
50 class SdfAssetPath;
51 
52 // -------------------------------------------------------------------------- //
53 // XFORMABLE                                                                  //
54 // -------------------------------------------------------------------------- //
55 
56 /// \class UsdGeomXformable
57 ///
58 /// Base class for all transformable prims, which allows arbitrary
59 /// sequences of component affine transformations to be encoded.
60 ///
61 /// \note
62 /// You may find it useful to review \ref UsdGeom_LinAlgBasics while reading
63 /// this class description.
64 ///
65 /// <b>Supported Component Transformation Operations</b>
66 ///
67 /// UsdGeomXformable currently supports arbitrary sequences of the following
68 /// operations, each of which can be encoded in an attribute of the proper
69 /// shape in any supported precision:
70 /// \li translate - 3D
71 /// \li scale     - 3D
72 /// \li rotateX   - 1D angle in degrees
73 /// \li rotateY   - 1D angle in degrees
74 /// \li rotateZ   - 1D angle in degrees
75 /// \li rotateABC - 3D where ABC can be any combination of the six principle
76 /// Euler Angle sets: XYZ, XZY, YXZ, YZX, ZXY, ZYX.  See
77 /// \ref usdGeom_rotationPackingOrder "note on rotation packing order"
78 /// \li orient    - 4D (quaternion)
79 /// \li transform - 4x4D
80 ///
81 /// <b>Creating a Component Transformation</b>
82 ///
83 /// To add components to a UsdGeomXformable prim, simply call AddXformOp()
84 /// with the desired op type, as enumerated in \ref UsdGeomXformOp::Type,
85 /// and the desired precision, which is one of \ref UsdGeomXformOp::Precision.
86 /// Optionally, you can also provide an "op suffix" for the operator that
87 /// disambiguates it from other components of the same type on the same prim.
88 /// Application-specific transform schemas can use the suffixes to fill a role
89 /// similar to that played by AbcGeom::XformOp's "Hint" enums for their own
90 /// round-tripping logic.
91 ///
92 /// We also provide specific "Add" API for each type, for clarity and
93 /// conciseness, e.g. AddTranslateOp(), AddRotateXYZOp() etc.
94 ///
95 /// AddXformOp() will return a UsdGeomXformOp object, which is a schema on a
96 /// newly created UsdAttribute that provides convenience API for authoring
97 /// and computing the component transformations.  The UsdGeomXformOp can then
98 /// be used to author any number of timesamples and default for the op.
99 ///
100 /// Each successive call to AddXformOp() adds an operator that will be applied
101 /// "more locally" than the preceding operator, just as if we were pushing
102 /// transforms onto a transformation stack - which is precisely what should
103 /// happen when the operators are consumed by a reader.
104 ///
105 /// \note
106 /// If you can, please try to use the UsdGeomXformCommonAPI, which wraps
107 /// the UsdGeomXformable with an interface in which Op creation is taken
108 /// care of for you, and there is a much higher chance that the data you
109 /// author will be importable without flattening into other DCC's, as it
110 /// conforms to a fixed set of Scale-Rotate-Translate Ops.
111 ///
112 /// \sa \ref usdGeom_xformableExamples "Using the Authoring API"
113 ///
114 /// <b>Data Encoding and Op Ordering</b>
115 ///
116 /// Because there is no "fixed schema" of operations, all of the attributes
117 /// that encode transform operations are dynamic, and are scoped in
118 /// the namespace "xformOp". The second component of an attribute's name provides
119 /// the \em type of operation, as listed above.  An "xformOp" attribute can
120 /// have additional namespace components derived from the \em opSuffix argument
121 /// to the AddXformOp() suite of methods, which provides a preferred way of
122 /// naming the ops such that we can have multiple "translate" ops with unique
123 /// attribute names. For example, in the attribute named
124 /// "xformOp:translate:maya:pivot", "translate" is the type of operation and
125 /// "maya:pivot" is the suffix.
126 ///
127 /// The following ordered list of attribute declarations in usda
128 /// define a basic Scale-Rotate-Translate with XYZ Euler angles, wherein the
129 /// translation is double-precision, and the remainder of the ops are single,
130 /// in which we will:
131 ///
132 /// <ol>
133 /// <li> Scale by 2.0 in each dimension
134 /// <li> Rotate about the X, Y, and Z axes by 30, 60, and 90 degrees, respectively
135 /// <li> Translate by 100 units in the Y direction
136 /// </ol>
137 ///
138 /// \code
139 /// float3 xformOp:rotateXYZ = (30, 60, 90)
140 /// float3 xformOp:scale = (2, 2, 2)
141 /// double3 xformOp:translate = (0, 100, 0)
142 /// uniform token[] xformOpOrder = [ "xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale" ]
143 /// \endcode
144 ///
145 /// The attributes appear in the dictionary order in which USD, by default,
146 /// sorts them.  To ensure the ops are recovered and evaluated in the correct
147 /// order, the schema introduces the **xformOpOrder** attribute, which
148 /// contains the names of the op attributes, in the precise sequence in which
149 /// they should be pushed onto a transform stack. **Note** that the order is
150 /// opposite to what you might expect, given the matrix algebra described in
151 /// \ref UsdGeom_LinAlgBasics.  This also dictates order of op creation,
152 /// since each call to AddXformOp() adds a new op to the end of the
153 /// \b xformOpOrder array, as a new "most-local" operation.  See
154 /// \ref usdGeom_xformableExamples "Example 2 below" for C++ code that could
155 /// have produced this USD.
156 ///
157 /// If it were important for the prim's rotations to be independently
158 /// overridable, we could equivalently (at some performance cost) encode
159 /// the transformation also like so:
160 /// \code
161 /// float xformOp:rotateX = 30
162 /// float xformOp:rotateY = 60
163 /// float xformOp:rotateZ = 90
164 /// float3 xformOp:scale = (2, 2, 2)
165 /// double3 xformOp:translate = (0, 100, 0)
166 /// uniform token[] xformOpOrder = [ "xformOp:translate", "xformOp:rotateZ", "xformOp:rotateY", "xformOp:rotateX", "xformOp:scale" ]
167 /// \endcode
168 ///
169 /// Again, note that although we are encoding an XYZ rotation, the three
170 /// rotations appear in the **xformOpOrder** in the opposite order, with Z,
171 /// followed, by Y, followed by X.
172 ///
173 /// Were we to add a Maya-style scalePivot to the above example, it might
174 /// look like the following:
175 /// \code
176 /// float3 xformOp:rotateXYZ = (30, 60, 90)
177 /// float3 xformOp:scale = (2, 2, 2)
178 /// double3 xformOp:translate = (0, 100, 0)
179 /// double3 xformOp:translate:scalePivot
180 /// uniform token[] xformOpOrder = [ "xformOp:translate", "xformOp:rotateXYZ", "xformOp:translate:scalePivot", "xformOp:scale" ]
181 /// \endcode
182 ///
183 /// <b>Paired "Inverted" Ops</b>
184 ///
185 /// We have been claiming that the ordered list of ops serves as a set
186 /// of instructions to a transform stack, but you may have noticed in the last
187 /// example that there is a missing operation - the pivot for the scale op
188 /// needs to be applied in its inverse-form as a final (most local) op!  In the
189 /// AbcGeom::Xform schema, we would have encoded an actual "final" translation
190 /// op whose value was authored by the exporter as the negation of the pivot's
191 /// value.  However, doing so would be brittle in USD, given that each op can
192 /// be independently overridden, and the constraint that one attribute must be
193 /// maintained as the negation of the other in order for successful
194 /// re-importation of the schema cannot be expressed in USD.
195 ///
196 /// Our solution leverages the **xformOpOrder** member of the schema, which,
197 /// in addition to ordering the ops, may also contain one of two special
198 /// tokens that address the paired op and "stack resetting" behavior.
199 ///
200 /// The "paired op" behavior is encoded as an "!invert!" prefix in
201 /// \b xformOpOrder, as the result of an AddXformOp(isInverseOp=True) call.
202 /// The \b xformOpOrder for the last example would look like:
203 /// \code
204 /// uniform token[] xformOpOrder = [ "xformOp:translate", "xformOp:rotateXYZ", "xformOp:translate:scalePivot", "xformOp:scale", "!invert!xformOp:translate:scalePivot" ]
205 /// \endcode
206 ///
207 /// When asked for its value via UsdGeomXformOp::GetOpTransform(), an
208 /// "inverted" Op (i.e. the "inverted" half of a set of paired Ops) will fetch
209 /// the value of its paired attribute and return its negation.  This works for
210 /// all op types - an error will be issued if a "transform" type op is singular
211 /// and cannot be inverted. When getting the authored value of an inverted op
212 /// via UsdGeomXformOp::Get(), the raw, uninverted value of the associated
213 /// attribute is returned.
214 ///
215 /// For the sake of robustness, <b>setting a value on an inverted op is disallowed.</b>
216 /// Attempting to set a value on an inverted op will result in a coding error
217 /// and no value being set.
218 ///
219 /// <b>Resetting the Transform Stack</b>
220 ///
221 /// The other special op/token that can appear in \em xformOpOrder is
222 /// \em "!resetXformStack!", which, appearing as the first element of
223 /// \em xformOpOrder, indicates this prim should not inherit the transformation
224 /// of its namespace parent.  See SetResetXformStack()
225 ///
226 /// <b>Expected Behavior for "Missing" Ops</b>
227 ///
228 /// If an importer expects Scale-Rotate-Translate operations, but a prim
229 /// has only translate and rotate ops authored, the importer should assume
230 /// an identity scale.  This allows us to optimize the data a bit, if only
231 /// a few components of a very rich schema (like Maya's) are authored in the
232 /// app.
233 ///
234 /// \anchor usdGeom_xformableExamples
235 /// <b>Using the C++ API</b>
236 ///
237 /// #1. Creating a simple transform matrix encoding
238 /// \snippet examples.cpp CreateMatrixWithDefault
239 ///
240 /// #2. Creating the simple SRT from the example above
241 /// \snippet examples.cpp CreateExampleSRT
242 ///
243 /// #3. Creating a parameterized SRT with pivot using UsdGeomXformCommonAPI
244 /// \snippet examples.cpp CreateSRTWithDefaults
245 ///
246 /// #4. Creating a rotate-only pivot transform with animated
247 /// rotation and translation
248 /// \snippet examples.cpp CreateAnimatedTransform
249 ///
250 ///
251 ///
252 class UsdGeomXformable : public UsdGeomImageable
253 {
254 public:
255     /// Compile time constant representing what kind of schema this class is.
256     ///
257     /// \sa UsdSchemaKind
258     static const UsdSchemaKind schemaKind = UsdSchemaKind::AbstractTyped;
259 
260     /// Construct a UsdGeomXformable on UsdPrim \p prim .
261     /// Equivalent to UsdGeomXformable::Get(prim.GetStage(), prim.GetPath())
262     /// for a \em valid \p prim, but will not immediately throw an error for
263     /// an invalid \p prim
264     explicit UsdGeomXformable(const UsdPrim& prim=UsdPrim())
UsdGeomImageable(prim)265         : UsdGeomImageable(prim)
266     {
267     }
268 
269     /// Construct a UsdGeomXformable on the prim held by \p schemaObj .
270     /// Should be preferred over UsdGeomXformable(schemaObj.GetPrim()),
271     /// as it preserves SchemaBase state.
UsdGeomXformable(const UsdSchemaBase & schemaObj)272     explicit UsdGeomXformable(const UsdSchemaBase& schemaObj)
273         : UsdGeomImageable(schemaObj)
274     {
275     }
276 
277     /// Destructor.
278     USDGEOM_API
279     virtual ~UsdGeomXformable();
280 
281     /// Return a vector of names of all pre-declared attributes for this schema
282     /// class and all its ancestor classes.  Does not include attributes that
283     /// may be authored by custom/extended methods of the schemas involved.
284     USDGEOM_API
285     static const TfTokenVector &
286     GetSchemaAttributeNames(bool includeInherited=true);
287 
288     /// Return a UsdGeomXformable holding the prim adhering to this
289     /// schema at \p path on \p stage.  If no prim exists at \p path on
290     /// \p stage, or if the prim at that path does not adhere to this schema,
291     /// return an invalid schema object.  This is shorthand for the following:
292     ///
293     /// \code
294     /// UsdGeomXformable(stage->GetPrimAtPath(path));
295     /// \endcode
296     ///
297     USDGEOM_API
298     static UsdGeomXformable
299     Get(const UsdStagePtr &stage, const SdfPath &path);
300 
301 
302 protected:
303     /// Returns the kind of schema this class belongs to.
304     ///
305     /// \sa UsdSchemaKind
306     USDGEOM_API
307     UsdSchemaKind _GetSchemaKind() const override;
308 
309 private:
310     // needs to invoke _GetStaticTfType.
311     friend class UsdSchemaRegistry;
312     USDGEOM_API
313     static const TfType &_GetStaticTfType();
314 
315     static bool _IsTypedSchema();
316 
317     // override SchemaBase virtuals.
318     USDGEOM_API
319     const TfType &_GetTfType() const override;
320 
321 public:
322     // --------------------------------------------------------------------- //
323     // XFORMOPORDER
324     // --------------------------------------------------------------------- //
325     /// Encodes the sequence of transformation operations in the
326     /// order in which they should be pushed onto a transform stack while
327     /// visiting a UsdStage's prims in a graph traversal that will effect
328     /// the desired positioning for this prim and its descendant prims.
329     ///
330     /// You should rarely, if ever, need to manipulate this attribute directly.
331     /// It is managed by the AddXformOp(), SetResetXformStack(), and
332     /// SetXformOpOrder(), and consulted by GetOrderedXformOps() and
333     /// GetLocalTransformation().
334     ///
335     /// | ||
336     /// | -- | -- |
337     /// | Declaration | `uniform token[] xformOpOrder` |
338     /// | C++ Type | VtArray<TfToken> |
339     /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->TokenArray |
340     /// | \ref SdfVariability "Variability" | SdfVariabilityUniform |
341     USDGEOM_API
342     UsdAttribute GetXformOpOrderAttr() const;
343 
344     /// See GetXformOpOrderAttr(), and also
345     /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
346     /// If specified, author \p defaultValue as the attribute's default,
347     /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
348     /// the default for \p writeSparsely is \c false.
349     USDGEOM_API
350     UsdAttribute CreateXformOpOrderAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;
351 
352 public:
353     // ===================================================================== //
354     // Feel free to add custom code below this line, it will be preserved by
355     // the code generator.
356     //
357     // Just remember to:
358     //  - Close the class declaration with };
359     //  - Close the namespace with PXR_NAMESPACE_CLOSE_SCOPE
360     //  - Close the include guard with #endif
361     // ===================================================================== //
362     // --(BEGIN CUSTOM CODE)--
363 
364     /// \class XformQuery
365     ///
366     /// Helper class that caches the ordered vector of UsGeomXformOps that
367     /// contribute to the local transformation of an xformable prim
368     ///
369     /// Internally, the class initializes UsdAttributeQuery objects for the
370     /// xformOp attributes in order to facilitate efficient querying of their
371     /// values.
372     ///
373     /// \note This object does not listen to change notification. If a
374     /// consumer is holding onto a UsdGeomXformable::XformQuery object, it is
375     /// their responsibility to dispose of it, in response to a resync
376     /// change to the associated xformOp attributes. The class provides the
377     /// convenience method IncludesXformOpAttr for this purpose.
378     ///
379     class XformQuery {
380         public:
XformQuery()381             XformQuery():
382                 _resetsXformStack(false)
383             { }
384 
385             /// Constructs an XformQuery object for the given xformable prim.
386             /// Caches the ordered xformOps and initializes an UsdAttributeQuery
387             /// internally for all the associated attributes.
388             USDGEOM_API
389             XformQuery(const UsdGeomXformable &xformable);
390 
391             /// Utilizes the internally cached UsdAttributeQuery's to efficiently
392             /// compute the transform value at the given \p time.
393             USDGEOM_API
394             bool GetLocalTransformation(GfMatrix4d *transform,
395                                         const UsdTimeCode time) const;
396 
397             /// Returns whether the xformable resets its parent's transformation.
GetResetXformStack()398             bool GetResetXformStack() const {
399                 return _resetsXformStack;
400             }
401 
402             /// Returns whether the xform value might change over time.
403             USDGEOM_API
404             bool TransformMightBeTimeVarying() const;
405 
406             /// Sets the vector of times at which xformOp samples have been
407             /// authored in the cached set of xform ops.
408             ///
409             /// \sa UsdXformable::GetTimeSamples
410             USDGEOM_API
411             bool GetTimeSamples(std::vector<double> *times) const;
412 
413             /// Sets the vector of times in the \p interval at which xformOp
414             /// samples have been authored in the cached set of xform ops.
415             ///
416             /// \sa UsdXformable::GetTimeSamples
417             USDGEOM_API
418             bool GetTimeSamplesInInterval(const GfInterval &interval,
419                                           std::vector<double> *times) const;
420 
421             /// Returns whether the given attribute affects the local
422             /// transformation computed for this query.
423             USDGEOM_API
424             bool IsAttributeIncludedInLocalTransform(
425                 const TfToken &attrName) const;
426 
427         private:
428             // Cached copy of the vector of ordered xform ops.
429             std::vector<UsdGeomXformOp> _xformOps;
430 
431             // Cache whether the xformable has !resetsXformStack! in its
432             // xformOpOrder.
433             bool _resetsXformStack;
434     };
435 
436     /// Add an affine transformation to the local stack represented by this
437     /// Xformable.  This will fail if there is already a transform operation
438     /// of the same name in the ordered ops on this prim (i.e. as returned
439     /// by GetOrderedXformOps()), or if an op of the same name exists at all
440     /// on the prim with a different precision than that specified.
441     ///
442     /// The newly created operation will become the most-locally applied
443     /// transformation on the prim, and will appear last in the list
444     /// returned by GetOrderedXformOps(). It is OK to begin authoring values
445     /// to the returned UsdGeomXformOp immediately, interspersed with
446     /// subsequent calls to AddXformOp() - just note the order of application,
447     /// which \em can be changed at any time (and in stronger layers) via
448     /// SetXformOpOrder().
449     ///
450     /// \param opType is the type of transform operation, one of
451     ///        \ref UsdGeomXformOp::Type.
452     /// \param precision allows you to specify the precision with which you
453     ///        desire to encode the data. This should be one of the values in
454     ///        the enum \ref UsdGeomXformOp::Precision .
455     /// \param opSuffix allows you to specify the purpose/meaning of the op in
456     ///        the stack. When opSuffix is specified, the associated attribute's
457     ///        name is set to "xformOp:<opType>:<opSuffix>".
458     /// \param isInverseOp is used to indicate an inverse transformation
459     ///        operation.
460     ///
461     /// \return a UsdGeomXformOp that can be used to author to the operation.
462     ///         An error is issued and the returned object will be invalid
463     ///         (evaluate to false) if the op being added already exists in
464     ///         \ref GetXformOpOrderAttr() "xformOpOrder" or if the
465     ///         arguments supplied are invalid.
466     ///
467     /// \note If the attribute associated with the op already exists, but isn't
468     /// of the requested precision, a coding error is issued, but a valid
469     /// xformOp is returned with the existing attribute.
470     ///
471     USDGEOM_API
472     UsdGeomXformOp AddXformOp(UsdGeomXformOp::Type const opType,
473                               UsdGeomXformOp::Precision const
474                               precision=UsdGeomXformOp::PrecisionDouble,
475                               TfToken const &opSuffix = TfToken(),
476                               bool isInverseOp=false) const;
477 
478     /// Add a translate operation to the local stack represented by this
479     /// xformable.
480     ///
481     /// \sa AddXformOp()
482     USDGEOM_API
483     UsdGeomXformOp AddTranslateOp(
484         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionDouble,
485         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
486 
487     /// Add a scale operation to the local stack represented by this
488     /// xformable.
489     ///
490     /// \sa AddXformOp()
491     USDGEOM_API
492     UsdGeomXformOp AddScaleOp(
493         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
494         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
495 
496     /// Add a rotation about the X-axis to the local stack represented by
497     /// this xformable.
498     ///
499     /// Set the angle value of the resulting UsdGeomXformOp <b>in degrees</b>
500     /// \sa AddXformOp()
501     USDGEOM_API
502     UsdGeomXformOp AddRotateXOp(
503         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
504         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
505 
506     /// Add a rotation about the YX-axis to the local stack represented by
507     /// this xformable.
508     ///
509     /// Set the angle value of the resulting UsdGeomXformOp <b>in degrees</b>
510     /// \sa AddXformOp()
511     USDGEOM_API
512     UsdGeomXformOp AddRotateYOp(
513         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
514         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
515 
516     /// Add a rotation about the Z-axis to the local stack represented by
517     /// this xformable.
518     ///
519     /// \sa AddXformOp()
520     USDGEOM_API
521     UsdGeomXformOp AddRotateZOp(
522         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
523         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
524 
525     /// Add a rotation op with XYZ rotation order to the local stack
526     /// represented by this xformable.
527     ///
528     /// Set the angle value of the resulting UsdGeomXformOp <b>in degrees</b>
529     /// \sa AddXformOp(), \ref usdGeom_rotationPackingOrder "note on angle packing order"
530     USDGEOM_API
531     UsdGeomXformOp AddRotateXYZOp(
532         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
533         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
534 
535     /// Add a rotation op with XZY rotation order to the local stack
536     /// represented by this xformable.
537     ///
538     /// Set the angle values of the resulting UsdGeomXformOp <b>in degrees</b>
539     /// \sa AddXformOp(), \ref usdGeom_rotationPackingOrder "note on angle packing order"
540     USDGEOM_API
541     UsdGeomXformOp AddRotateXZYOp(
542         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
543         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
544 
545     /// Add a rotation op with YXZ rotation order to the local stack
546     /// represented by this xformable.
547     ///
548     /// Set the angle values of the resulting UsdGeomXformOp <b>in degrees</b>
549     /// \sa AddXformOp(), \ref usdGeom_rotationPackingOrder "note on angle packing order"
550     USDGEOM_API
551     UsdGeomXformOp AddRotateYXZOp(
552         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
553         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
554 
555     /// Add a rotation op with YZX rotation order to the local stack
556     /// represented by this xformable.
557     ///
558     /// Set the angle values of the resulting UsdGeomXformOp <b>in degrees</b>
559     /// \sa AddXformOp(), \ref usdGeom_rotationPackingOrder "note on angle packing order"
560     USDGEOM_API
561     UsdGeomXformOp AddRotateYZXOp(
562         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
563         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
564 
565     /// Add a rotation op with ZXY rotation order to the local stack
566     /// represented by this xformable.
567     ///
568     /// Set the angle values of the resulting UsdGeomXformOp <b>in degrees</b>
569     /// \sa AddXformOp(), \ref usdGeom_rotationPackingOrder "note on angle packing order"
570     USDGEOM_API
571     UsdGeomXformOp AddRotateZXYOp(
572         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
573         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
574 
575     /// Add a rotation op with ZYX rotation order to the local stack
576     /// represented by this xformable.
577     ///
578     /// Set the angle values of the resulting UsdGeomXformOp <b>in degrees</b>
579     /// \sa AddXformOp(), \ref usdGeom_rotationPackingOrder "note on angle packing order"
580     USDGEOM_API
581     UsdGeomXformOp AddRotateZYXOp(
582         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
583         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
584 
585     /// Add a orient op (arbitrary axis/angle rotation) to the local stack
586     /// represented by this xformable.
587     ///
588     /// \sa AddXformOp()
589     USDGEOM_API
590     UsdGeomXformOp AddOrientOp(
591         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionFloat,
592         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
593 
594     /// Add a tranform op (4x4 matrix transformation) to the local stack
595     /// represented by this xformable.
596     ///
597     /// \sa AddXformOp()
598     ///
599     /// Note: This method takes a precision argument only to be consistent
600     /// with the other types of xformOps. The only valid precision here is
601     /// double since matrix values cannot be encoded in floating-pt precision
602     /// in Sdf.
603     USDGEOM_API
604     UsdGeomXformOp AddTransformOp(
605         UsdGeomXformOp::Precision const precision=UsdGeomXformOp::PrecisionDouble,
606         TfToken const &opSuffix = TfToken(), bool isInverseOp=false) const;
607 
608     /// Specify whether this prim's transform should reset the transformation
609     /// stack inherited from its parent prim.
610     ///
611     /// By default, parent transforms are inherited. SetResetXformStack() can be
612     /// called at any time during authoring, but will always add a
613     /// '!resetXformStack!' op as the \em first op in the ordered list, if one
614     /// does not exist already.  If one already exists, and \p resetXform is
615     /// false, it will remove all ops upto and including the last
616     /// "!resetXformStack!" op.
617     USDGEOM_API
618     bool SetResetXformStack(bool resetXform) const;
619 
620     /// Does this prim reset its parent's inherited transformation?
621     ///
622     /// Returns true if "!resetXformStack!" appears \em anywhere in xformOpOrder.
623     /// When this returns true, all ops upto the last "!resetXformStack!" in
624     /// xformOpOrder are ignored when computing the local transformation.
625     ///
626     USDGEOM_API
627     bool GetResetXformStack() const;
628 
629     /// Reorder the already-existing transform ops on this prim.
630     ///
631     /// All elements in \p orderedXformOps must be valid and represent attributes
632     /// on this prim.  Note that it is \em not required that all the existing
633     /// operations be present in \p orderedXformOps, so this method can be used to
634     /// completely change the transformation structure applied to the prim.
635     ///
636     /// If \p resetXformStack is set to true, then "!resetXformOp! will be
637     /// set as the first op in xformOpOrder, to indicate that the prim does
638     /// not inherit its parent's transformation.
639     ///
640     /// \note If you wish to re-specify a prim's transformation completely in
641     /// a stronger layer, you should first call this method with an \em empty
642     /// \p orderedXformOps vector.  From there you can call AddXformOp() just as if
643     /// you were authoring to the prim from scratch.
644     ///
645     /// \return false if any of the elements of \p orderedXformOps are not extant
646     /// on this prim, or if an error occurred while authoring the ordering
647     /// metadata.  Under either condition, no scene description is authored.
648     ///
649     /// \sa GetOrderedXformOps()
650     USDGEOM_API
651     bool SetXformOpOrder(std::vector<UsdGeomXformOp> const &orderedXformOps,
652                          bool resetXformStack = false) const;
653 
654     /// Return the ordered list of transform operations to be applied to
655     /// this prim, in least-to-most-local order.  This is determined by the
656     /// intersection of authored op-attributes and the explicit ordering of
657     /// those attributes encoded in the \c xformOpOrder attribute on this prim.
658     /// Any entries in \c xformOpOrder that do not correspond to valid
659     /// attributes on the xformable prim are skipped and a warning is issued.
660     ///
661     /// A UsdGeomTransformable that has not had any ops added via AddXformOp()
662     /// will return an empty vector.
663     ///
664     /// The function also sets \p resetsXformStack to true if "!resetXformStack!"
665     /// appears \em anywhere in xformOpOrder (i.e., if the prim resets its
666     /// parent's inherited transformation).
667     ///
668     /// \note A coding error is issued if resetsXformStack is NULL.
669     ///
670     /// \sa GetResetXformStack()
671     USDGEOM_API
672     std::vector<UsdGeomXformOp> GetOrderedXformOps(bool *resetsXformStack) const;
673 
674     /// Clears the local transform stack.
675     USDGEOM_API
676     bool ClearXformOpOrder() const;
677 
678     /// Clears the existing local transform stack and creates a new xform op of
679     /// type 'transform'.
680     ///
681     /// This API is provided for convenience since this is the most common
682     /// xform authoring operation.
683     ///
684     /// \sa ClearXformOpOrder()
685     /// \sa AddTransformOp()
686     USDGEOM_API
687     UsdGeomXformOp MakeMatrixXform() const;
688 
689     /// Determine whether there is any possibility that this prim's \em local
690     /// transformation may vary over time.
691     ///
692     /// The determination is based on a snapshot of the authored state of the
693     /// op attributes on the prim, and may become invalid in the face of
694     /// further authoring.
695     USDGEOM_API
696     bool TransformMightBeTimeVarying() const;
697 
698     /// \overload
699     /// Determine whether there is any possibility that this prim's \em local
700     /// transformation may vary over time, using a pre-fetched (cached) list of
701     /// ordered xform ops supplied by the client.
702     ///
703     /// The determination is based on a snapshot of the authored state of the
704     /// op attributes on the prim, and may become invalid in the face of
705     /// further authoring.
706     USDGEOM_API
707     bool TransformMightBeTimeVarying(
708         const std::vector<UsdGeomXformOp> &ops) const;
709 
710     /// Sets \p times to the union of all the timesamples at which xformOps that
711     /// are included in the xformOpOrder attribute are authored.
712     ///
713     /// This clears the \p times vector before accumulating sample times
714     /// from all the xformOps.
715     ///
716     /// \sa UsdAttribute::GetTimeSamples
717     USDGEOM_API
718     bool GetTimeSamples(std::vector<double> *times) const;
719 
720     /// Sets \p times to the union of all the timesamples in the interval,
721     /// \p interval, at which xformOps that are included in the xformOpOrder
722     /// attribute are authored.
723     ///
724     /// This clears the \p times vector before accumulating sample times
725     /// from all the xformOps.
726     ///
727     /// \sa UsdAttribute::GetTimeSamples
728     USDGEOM_API
729     bool GetTimeSamplesInInterval(const GfInterval &interval,
730                                   std::vector<double> *times) const;
731 
732     /// Returns the union of all the timesamples at which the attributes
733     /// belonging to the given \p orderedXformOps are authored.
734     ///
735     /// This clears the \p times vector before accumulating sample times
736     /// from \p orderedXformOps.
737     ///
738     /// \sa UsdGeomXformable::GetTimeSamples
739     USDGEOM_API
740     static bool GetTimeSamples(
741         std::vector<UsdGeomXformOp> const &orderedXformOps,
742         std::vector<double> *times);
743 
744     /// Returns the union of all the timesamples in the \p interval
745     /// at which the attributes belonging to the given \p orderedXformOps
746     /// are authored.
747     ///
748     /// This clears the \p times vector before accumulating sample times
749     /// from \p orderedXformOps.
750     ///
751     /// \sa UsdGeomXformable::GetTimeSamplesInInterval
752     USDGEOM_API
753     static bool GetTimeSamplesInInterval(
754         std::vector<UsdGeomXformOp> const &orderedXformOps,
755         const GfInterval &interval,
756         std::vector<double> *times);
757 
758     /// Computes the fully-combined, local-to-parent transformation for this prim.
759     ///
760     /// If a client does not need to manipulate the individual ops themselves,
761     /// and requires only the combined transform on this prim, this method will
762     /// take care of all the data marshalling and linear algebra needed to
763     /// combine the ops into a 4x4 affine transformation matrix, in
764     /// double-precision, regardless of the precision of the op inputs.
765     ///
766     /// \param transform is the output parameter that will hold the local
767     ///        transform.
768     /// \param resetsXformStack is the output parameter that informs client
769     ///        whether they need to reset the transform stack before pushing
770     ///        \p transform.
771     /// \param time is the UsdTimeCode at which to sample the ops.
772     ///
773     /// \return true on success, false if there was an error reading data.
774     ///
775     /// \note A coding error is issued if \p transform or \p resetsXformStack
776     ///       is NULL.
777     ///
778     USDGEOM_API
779     bool GetLocalTransformation(
780         GfMatrix4d *transform,
781         bool *resetsXformStack,
782         const UsdTimeCode time = UsdTimeCode::Default()) const;
783 
784     /// \overload
785     /// Computes the fully-combined, local-to-parent transformation for this
786     /// prim as efficiently as possible, using a pre-fetched (cached) list of
787     /// ordered xform ops supplied by the client.
788     ///
789     /// \param transform is the output parameter that will hold the local
790     ///        transform.
791     /// \param resetsXformStack is the output parameter that informs client
792     ///        whether they need to reset the transform stack before pushing
793     ///        \p transform.
794     /// \param ops is the ordered set of xform ops for this prim, and will be
795     ///        queried without any validity checking. Passing this in can save
796     ///        significant value-resolution costs, if the client is able to
797     ///        retain this data from a call to GetOrderedXformOps().
798     /// \param time is the UsdTimeCode at which to sample the ops.
799     ///
800     /// \return true on success, false if there was an error reading data.
801     ///
802     /// \note A coding error is issued if \p transform or \p resetsXformStack
803     ///       is NULL.
804     ///
805     USDGEOM_API
806     bool GetLocalTransformation(GfMatrix4d *transform,
807                                 bool *resetsXformStack,
808                                 const std::vector<UsdGeomXformOp> &ops,
809                                 const UsdTimeCode time = UsdTimeCode::Default()) const;
810 
811     /// \overload
812     /// This is a static version of the preceding function that takes
813     /// a cached list of ordered xform ops.
814     ///
815     /// \param transform is the output parameter that will hold the local
816     ///        transform.
817     /// \param ops is the ordered set of xform ops that must be combined
818     ///        together to compute the local transformation.
819     /// \param time is the UsdTimeCode at which to sample the ops.
820     ///
821     /// \return true on success, false if there was an error reading data.
822     ///
823     USDGEOM_API
824     static bool GetLocalTransformation(GfMatrix4d *transform,
825         std::vector<UsdGeomXformOp> const &ops,
826         const UsdTimeCode time);
827 
828     /// Returns true if the attribute named \p attrName could affect the local
829     /// transformation of an xformable prim.
830     USDGEOM_API
831     static bool IsTransformationAffectedByAttrNamed(const TfToken &attrName);
832 
833 private:
834     // Extracts the value of the xformOpOrder attribute. Returns false if
835     // the xformOpOrder attribute doesn't exist on the prim (eg. when the prim
836     // type is incompatible or if it's a pure over).
837     bool _GetXformOpOrderValue(VtTokenArray *xformOpOrder) const;
838 
839     // Helper function for getting xformops with or without attribute queries.
840     std::vector<UsdGeomXformOp>
841     _GetOrderedXformOps(bool *resetsXformStack,
842                         bool withAttributeQueries) const;
843 };
844 
845 PXR_NAMESPACE_CLOSE_SCOPE
846 
847 #endif
848