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