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 USDSHADE_GENERATED_MATERIALBINDINGAPI_H 25 #define USDSHADE_GENERATED_MATERIALBINDINGAPI_H 26 27 /// \file usdShade/materialBindingAPI.h 28 29 #include "pxr/pxr.h" 30 #include "pxr/usd/usdShade/api.h" 31 #include "pxr/usd/usd/apiSchemaBase.h" 32 #include "pxr/usd/usd/prim.h" 33 #include "pxr/usd/usd/stage.h" 34 #include "pxr/usd/usdShade/tokens.h" 35 36 #include "pxr/usd/usd/collectionAPI.h" 37 #include "pxr/usd/usdGeom/subset.h" 38 #include "pxr/usd/usdShade/material.h" 39 #include <tbb/concurrent_unordered_map.h> 40 41 #include "pxr/base/vt/value.h" 42 43 #include "pxr/base/gf/vec3d.h" 44 #include "pxr/base/gf/vec3f.h" 45 #include "pxr/base/gf/matrix4d.h" 46 47 #include "pxr/base/tf/token.h" 48 #include "pxr/base/tf/type.h" 49 50 PXR_NAMESPACE_OPEN_SCOPE 51 52 class SdfAssetPath; 53 54 // -------------------------------------------------------------------------- // 55 // MATERIALBINDINGAPI // 56 // -------------------------------------------------------------------------- // 57 58 /// \class UsdShadeMaterialBindingAPI 59 /// 60 /// UsdShadeMaterialBindingAPI is an API schema that provides an 61 /// interface for binding materials to prims or collections of prims 62 /// (represented by UsdCollectionAPI objects). 63 /// 64 /// In the USD shading model, each renderable gprim computes a single 65 /// <b>resolved Material</b> that will be used to shade the gprim (exceptions, 66 /// of course, for gprims that possess UsdGeomSubsets, as each subset can be 67 /// shaded by a different Material). A gprim <b>and each of its ancestor 68 /// prims</b> can possess, through the MaterialBindingAPI, both a 69 /// <b>direct</b> binding to a Material, and any number of 70 /// <b>collection-based</b> bindings to Materials; each binding can be generic 71 /// or declared for a particular <b>purpose</b>, and given a specific <b>binding 72 /// strength</b>. It is the process of "material resolution" (see 73 /// \ref UsdShadeMaterialBindingAPI_MaterialResolution) that examines all of 74 /// these bindings, and selects the one Material that best matches the 75 /// client's needs. 76 /// 77 /// The intent of <b>purpose</b> is that each gprim should be able to resolve a 78 /// Material for any given purpose, which implies it can have differently bound 79 /// materials for different purposes. There are two <i>special</i> values of 80 /// <b>purpose</b> defined in UsdShade, although the API fully supports 81 /// specifying arbitrary values for it, for the sake of extensibility: 82 /// <ul><li><b>UsdShadeTokens->full</b>: to be used when the purpose of the 83 /// render is entirely to visualize the truest representation of a scene, 84 /// considering all lighting and material information, at highest fidelity.</li> 85 /// <li><b>UsdShadeTokens->preview</b>: to be used when the render is in 86 /// service of a goal other than a high fidelity "full" render (such as scene 87 /// manipulation, modeling, or realtime playback). Latency and speed are 88 /// generally of greater concern for preview renders, therefore preview 89 /// materials are generally designed to be "lighterweight" compared to full 90 /// materials.</li></ul> 91 /// A binding can also have no specific purpose at all, in which 92 /// case, it is considered to be the fallback or all-purpose binding (denoted 93 /// by the empty-valued token <b>UsdShadeTokens->allPurpose</b>). 94 /// 95 /// The <b>purpose</b> of a material binding is encoded in the name of the 96 /// binding relationship. 97 /// <ul><li> 98 /// In the case of a direct binding, the <i>allPurpose</i> binding is 99 /// represented by the relationship named <b>"material:binding"</b>. 100 /// Special-purpose direct bindings are represented by relationships named 101 /// <b>"material:binding:<i>purpose</i></b>. A direct binding relationship 102 /// must have a single target path that points to a <b>UsdShadeMaterial</b>.</li> 103 /// <li> 104 /// In the case of a collection-based binding, the <i>allPurpose</i> binding is 105 /// represented by a relationship named 106 /// "material:binding:collection:<i>bindingName</i>", where 107 /// <b>bindingName</b> establishes an identity for the binding that is unique 108 /// on the prim. Attempting to establish two collection bindings of the same 109 /// name on the same prim will result in the first binding simply being 110 /// overridden. A special-purpose collection-based binding is represented by a 111 /// relationship named "material:binding:collection:<i>purpose:bindingName</i>". 112 /// A collection-based binding relationship must have exacly two targets, one of 113 /// which should be a collection-path (see 114 /// ef UsdCollectionAPI::GetCollectionPath()) and the other should point to a 115 /// <b>UsdShadeMaterial</b>. In the future, we may allow a single collection 116 /// binding to target multiple collections, if we can establish a reasonable 117 /// round-tripping pattern for applications that only allow a single collection 118 /// to be associated with each Material. 119 /// </li> 120 /// </ul> 121 /// 122 /// <b>Note:</b> Both <b>bindingName</b> and <b>purpose</b> must be 123 /// non-namespaced tokens. This allows us to know the role of a binding 124 /// relationship simply from the number of tokens in it. 125 /// <ul><li><b>Two tokens</b>: the fallback, "all purpose", direct binding, 126 /// <i>material:binding</i></li> 127 /// <li><b>Three tokens</b>: a purpose-restricted, direct, fallback binding, 128 /// e.g. material:binding:preview</li> 129 /// <li><b>Four tokens</b>: an all-purpose, collection-based binding, e.g. 130 /// material:binding:collection:metalBits</li> 131 /// <li><b>Five tokens</b>: a purpose-restricted, collection-based binding, 132 /// e.g. material:binding:collection:full:metalBits</li> 133 /// </ul> 134 /// 135 /// A <b>binding-strength</b> value is used to specify whether a binding 136 /// authored on a prim should be weaker or stronger than bindings that appear 137 /// lower in namespace. We encode the binding strength with as token-valued 138 /// metadata <b>'bindMaterialAs'</b> for future flexibility, even though for 139 /// now, there are only two possible values: 140 /// <i>UsdShadeTokens->weakerThanDescendants</i> and 141 /// <i>UsdShadeTokens->strongerThanDescendants</i>. When binding-strength is 142 /// not authored (i.e. empty) on a binding-relationship, the default behavior 143 /// matches UsdShadeTokens->weakerThanDescendants. 144 /// 145 /// \note If a material binding relationship is a built-in property defined as 146 /// part of a typed prim's schema, a fallback value should not be provided for 147 /// it. This is because the "material resolution" algorithm only conisders 148 /// <i>authored</i> properties. 149 /// 150 /// 151 class UsdShadeMaterialBindingAPI : public UsdAPISchemaBase 152 { 153 public: 154 /// Compile time constant representing what kind of schema this class is. 155 /// 156 /// \sa UsdSchemaKind 157 static const UsdSchemaKind schemaKind = UsdSchemaKind::SingleApplyAPI; 158 159 /// Construct a UsdShadeMaterialBindingAPI on UsdPrim \p prim . 160 /// Equivalent to UsdShadeMaterialBindingAPI::Get(prim.GetStage(), prim.GetPath()) 161 /// for a \em valid \p prim, but will not immediately throw an error for 162 /// an invalid \p prim 163 explicit UsdShadeMaterialBindingAPI(const UsdPrim& prim=UsdPrim()) UsdAPISchemaBase(prim)164 : UsdAPISchemaBase(prim) 165 { 166 } 167 168 /// Construct a UsdShadeMaterialBindingAPI on the prim held by \p schemaObj . 169 /// Should be preferred over UsdShadeMaterialBindingAPI(schemaObj.GetPrim()), 170 /// as it preserves SchemaBase state. UsdShadeMaterialBindingAPI(const UsdSchemaBase & schemaObj)171 explicit UsdShadeMaterialBindingAPI(const UsdSchemaBase& schemaObj) 172 : UsdAPISchemaBase(schemaObj) 173 { 174 } 175 176 /// Destructor. 177 USDSHADE_API 178 virtual ~UsdShadeMaterialBindingAPI(); 179 180 /// Return a vector of names of all pre-declared attributes for this schema 181 /// class and all its ancestor classes. Does not include attributes that 182 /// may be authored by custom/extended methods of the schemas involved. 183 USDSHADE_API 184 static const TfTokenVector & 185 GetSchemaAttributeNames(bool includeInherited=true); 186 187 /// Return a UsdShadeMaterialBindingAPI holding the prim adhering to this 188 /// schema at \p path on \p stage. If no prim exists at \p path on 189 /// \p stage, or if the prim at that path does not adhere to this schema, 190 /// return an invalid schema object. This is shorthand for the following: 191 /// 192 /// \code 193 /// UsdShadeMaterialBindingAPI(stage->GetPrimAtPath(path)); 194 /// \endcode 195 /// 196 USDSHADE_API 197 static UsdShadeMaterialBindingAPI 198 Get(const UsdStagePtr &stage, const SdfPath &path); 199 200 201 /// Returns true if this <b>single-apply</b> API schema can be applied to 202 /// the given \p prim. If this schema can not be a applied to the prim, 203 /// this returns false and, if provided, populates \p whyNot with the 204 /// reason it can not be applied. 205 /// 206 /// Note that if CanApply returns false, that does not necessarily imply 207 /// that calling Apply will fail. Callers are expected to call CanApply 208 /// before calling Apply if they want to ensure that it is valid to 209 /// apply a schema. 210 /// 211 /// \sa UsdPrim::GetAppliedSchemas() 212 /// \sa UsdPrim::HasAPI() 213 /// \sa UsdPrim::CanApplyAPI() 214 /// \sa UsdPrim::ApplyAPI() 215 /// \sa UsdPrim::RemoveAPI() 216 /// 217 USDSHADE_API 218 static bool 219 CanApply(const UsdPrim &prim, std::string *whyNot=nullptr); 220 221 /// Applies this <b>single-apply</b> API schema to the given \p prim. 222 /// This information is stored by adding "MaterialBindingAPI" to the 223 /// token-valued, listOp metadata \em apiSchemas on the prim. 224 /// 225 /// \return A valid UsdShadeMaterialBindingAPI object is returned upon success. 226 /// An invalid (or empty) UsdShadeMaterialBindingAPI object is returned upon 227 /// failure. See \ref UsdPrim::ApplyAPI() for conditions 228 /// resulting in failure. 229 /// 230 /// \sa UsdPrim::GetAppliedSchemas() 231 /// \sa UsdPrim::HasAPI() 232 /// \sa UsdPrim::CanApplyAPI() 233 /// \sa UsdPrim::ApplyAPI() 234 /// \sa UsdPrim::RemoveAPI() 235 /// 236 USDSHADE_API 237 static UsdShadeMaterialBindingAPI 238 Apply(const UsdPrim &prim); 239 240 protected: 241 /// Returns the kind of schema this class belongs to. 242 /// 243 /// \sa UsdSchemaKind 244 USDSHADE_API 245 UsdSchemaKind _GetSchemaKind() const override; 246 247 private: 248 // needs to invoke _GetStaticTfType. 249 friend class UsdSchemaRegistry; 250 USDSHADE_API 251 static const TfType &_GetStaticTfType(); 252 253 static bool _IsTypedSchema(); 254 255 // override SchemaBase virtuals. 256 USDSHADE_API 257 const TfType &_GetTfType() const override; 258 259 public: 260 // ===================================================================== // 261 // Feel free to add custom code below this line, it will be preserved by 262 // the code generator. 263 // 264 // Just remember to: 265 // - Close the class declaration with }; 266 // - Close the namespace with PXR_NAMESPACE_CLOSE_SCOPE 267 // - Close the include guard with #endif 268 // ===================================================================== // 269 // --(BEGIN CUSTOM CODE)-- 270 271 /// \anchor UsdShadeMaterialBindingAPI_SchemaProperties 272 /// \name Schema property and associated data retrieval API 273 /// 274 /// This section contains API for fetching the two kinds of binding 275 /// relationships and for computing the corresponding bindings. 276 /// 277 /// @{ 278 279 /// Returns the direct material-binding relationship on this prim for the 280 /// given material purpose. 281 /// 282 /// The material purpose of the relationship that's returned will match 283 /// the specified \p materialPurpose. 284 USDSHADE_API 285 UsdRelationship GetDirectBindingRel( 286 const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const; 287 288 /// Returns the collection-based material-binding relationship with the 289 /// given \p bindingName and \p materialPurpose on this prim. 290 /// 291 /// For info on \p bindingName, see UsdShadeMaterialBindingAPI::Bind(). 292 /// The material purpose of the relationship that's returned will match 293 /// the specified \p materialPurpose. 294 USDSHADE_API 295 UsdRelationship GetCollectionBindingRel( 296 const TfToken &bindingName, 297 const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const; 298 299 /// Returns the list of collection-based material binding relationships 300 /// on this prim for the given material purpose, \p materialPurpose. 301 /// 302 /// The returned list of binding relationships will be in native property 303 /// order. See UsdPrim::GetPropertyOrder(), UsdPrim::SetPropertyOrder(). 304 /// Bindings that appear earlier in the property order are considered to be 305 /// stronger than the ones that come later. See rule #6 in 306 /// \ref UsdShadeMaterialBindingAPI_MaterialResolution. 307 USDSHADE_API 308 std::vector<UsdRelationship> GetCollectionBindingRels( 309 const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const; 310 311 /// \class DirectBinding 312 /// This class represents a direct material binding. 313 class DirectBinding { 314 public: 315 /// Default constructor initializes a DirectBinding object with 316 /// invalid material and bindingRel data members. DirectBinding()317 DirectBinding() 318 {} 319 320 USDSHADE_API 321 explicit DirectBinding(const UsdRelationship &bindingRel); 322 323 /// Gets the material object that this direct binding binds to. 324 USDSHADE_API 325 UsdShadeMaterial GetMaterial() const; 326 327 /// Returns the path to the material that is bound to by this 328 /// direct binding. GetMaterialPath()329 const SdfPath &GetMaterialPath() const { 330 return _materialPath; 331 } 332 333 /// Returns the binding-relationship that represents this direct 334 /// binding. GetBindingRel()335 const UsdRelationship &GetBindingRel() const { 336 return _bindingRel; 337 } 338 339 /// Returns the purpose of the direct binding. GetMaterialPurpose()340 const TfToken &GetMaterialPurpose() const { 341 return _materialPurpose; 342 } 343 344 private: 345 // The path to the material that is bound to. 346 SdfPath _materialPath; 347 348 // The binding relationship. 349 UsdRelationship _bindingRel; 350 351 // The purpose of the material binding. 352 TfToken _materialPurpose; 353 }; 354 355 /// \class CollectionBinding 356 /// This struct is used to represent a collection-based material binding, 357 /// which contains two objects - a collection and a bound material. 358 class CollectionBinding { 359 public: 360 /// Default constructor initializes a CollectionBinding object with 361 /// invalid collection, material and bindingRel data members. CollectionBinding()362 CollectionBinding() 363 {} 364 365 /// Constructs a CollectionBinding object from the given collection- 366 /// binding relationship. This inspects the targets of the relationship 367 /// and determines the bound collection and the target material that 368 /// the collection is bound to. 369 USDSHADE_API 370 explicit CollectionBinding(const UsdRelationship &collBindingRel); 371 372 /// Constructs and returns the material object that this 373 /// collection-based binding binds to. 374 USDSHADE_API 375 UsdShadeMaterial GetMaterial() const; 376 377 /// Constructs and returns the CollectionAPI object for the collection 378 /// that is bound by this collection-binding. 379 USDSHADE_API 380 UsdCollectionAPI GetCollection() const; 381 382 /// Returns true if the CollectionBinding points to a valid material 383 /// and collection. IsValid()384 bool IsValid() const { 385 return GetCollection() && GetMaterial(); 386 } 387 /// Returns the path to the collection that is bound by this binding. GetCollectionPath()388 const SdfPath &GetCollectionPath() const { 389 return _collectionPath; 390 } 391 392 /// Returns the path to the material that is bound to by this binding. GetMaterialPath()393 const SdfPath &GetMaterialPath() const { 394 return _materialPath; 395 } 396 397 /// Returns the binding-relationship that represents this collection- 398 /// based binding. GetBindingRel()399 const UsdRelationship &GetBindingRel() const { 400 return _bindingRel; 401 } 402 403 private: 404 // The collection being bound. 405 SdfPath _collectionPath; 406 407 // The material that is bound to. 408 SdfPath _materialPath; 409 410 // The relationship that binds the collection to the material. 411 UsdRelationship _bindingRel; 412 }; 413 414 using CollectionBindingVector = std::vector<CollectionBinding>; 415 416 /// Computes and returns the direct binding for the given material purpose 417 /// on this prim. 418 /// 419 /// The returned binding always has the specified \p materialPurpose 420 /// (i.e. the all-purpose binding is not returned if a special purpose 421 /// binding is requested). 422 /// 423 /// If the direct binding is to a prim that is not a Material, this does not 424 /// generate an error, but the returned Material will be invalid (i.e. 425 /// evaluate to false). 426 USDSHADE_API 427 DirectBinding GetDirectBinding( 428 const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const; 429 430 /// Returns all the collection-based bindings on this prim for the given 431 /// material purpose. 432 /// 433 /// The returned CollectionBinding objects always have the specified 434 /// \p materialPurpose (i.e. the all-purpose binding is not returned if a 435 /// special purpose binding is requested). 436 /// 437 /// If one or more collection based bindings are to prims that are not 438 /// Materials, this does not generate an error, but the corresponding 439 /// Material(s) will be invalid (i.e. evaluate to false). 440 /// 441 /// The python version of this API returns a tuple containing the 442 /// vector of CollectionBinding objects and the corresponding vector 443 /// of binding relationships. 444 /// 445 /// The returned list of collection-bindings will be in native property 446 /// order of the associated binding relationships. See 447 /// UsdPrim::GetPropertyOrder(), UsdPrim::SetPropertyOrder(). 448 /// Binding relationships that come earlier in the list are considered to 449 /// be stronger than the ones that come later. See rule #6 in 450 /// \ref UsdShadeMaterialBindingAPI_MaterialResolution. 451 USDSHADE_API 452 CollectionBindingVector GetCollectionBindings( 453 const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const; 454 455 /// Resolves the 'bindMaterialAs' token-valued metadata on the given binding 456 /// relationship and returns it. 457 /// If the resolved value is empty, this returns the fallback value 458 /// UsdShadeTokens->weakerThanDescendants. 459 /// 460 /// \sa UsdShadeMaterialBindingAPI::SetMaterialBindingStrength() 461 USDSHADE_API 462 static TfToken GetMaterialBindingStrength( 463 const UsdRelationship &bindingRel); 464 465 /// Sets the 'bindMaterialAs' token-valued metadata on the given binding 466 /// relationship. 467 /// 468 /// If \p bindingStrength is <i>UsdShadeTokens->fallbackStrength</i>, the 469 /// value UsdShadeTokens->weakerThanDescendants is authored sparsely, i.e. 470 /// only when there is a different existing bindingStrength value. 471 /// To stamp out the bindingStrength value explicitly, clients can pass in 472 /// UsdShadeTokens->weakerThanDescendants or 473 /// UsdShadeTokens->strongerThanDescendants directly. 474 475 /// Returns true on success, false otherwise. 476 /// 477 /// \sa UsdShadeMaterialBindingAPI::GetMaterialBindingStrength() 478 USDSHADE_API 479 static bool SetMaterialBindingStrength( 480 const UsdRelationship &bindingRel, 481 const TfToken &bindingStrength); 482 483 /// @} 484 485 /// \anchor UsdShadeMaterialBindingAPI_Binding 486 /// \name Binding authoring and clearing API 487 /// 488 /// This section provides API for authoring and clearing both direct and 489 /// collection-based material bindings on a prim. 490 /// 491 /// @{ 492 493 /// Authors a direct binding to the given \p material on this prim. 494 /// 495 /// If \p bindingStrength is UsdShadeTokens->fallbackStrength, the value 496 /// UsdShadeTokens->weakerThanDescendants is authored sparsely. 497 /// To stamp out the bindingStrength value explicitly, clients can pass in 498 /// UsdShadeTokens->weakerThanDescendants or 499 /// UsdShadeTokens->strongerThanDescendants directly. 500 /// 501 /// If \p materialPurpose is specified and isn't equal to 502 /// UsdShadeTokens->allPurpose, the binding only applies to the specified 503 /// material purpose. 504 /// 505 /// Note that UsdShadeMaterialBindingAPI is a SingleAppliedAPI schema which 506 /// when applied updates the prim definition accordingly. This information 507 /// on the prim definition is helpful in multiple queries and more 508 /// performant. Hence its recommended to call 509 /// UsdShadeMaterialBindingAPI::Apply() when Binding a material. 510 /// 511 /// Returns true on success, false otherwise. 512 USDSHADE_API 513 bool Bind( 514 const UsdShadeMaterial &material, 515 const TfToken &bindingStrength=UsdShadeTokens->fallbackStrength, 516 const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const; 517 518 /// Authors a collection-based binding, which binds the given \p material 519 /// to the given \p collection on this prim. 520 /// 521 /// \p bindingName establishes an identity for the binding that is unique 522 /// on the prim. Attempting to establish two collection bindings of the same 523 /// name on the same prim will result in the first binding simply being 524 /// overridden. If \p bindingName is empty, it is set to the base-name of 525 /// the collection being bound (which is the collection-name with any 526 /// namespaces stripped out). If there are multiple collections with the 527 /// same base-name being bound at the same prim, clients should pass in a 528 /// unique binding name per binding, in order to preserve all bindings. 529 /// The binding name used in constructing the collection-binding 530 /// relationship name shoud not contain namespaces. Hence, a coding error 531 /// is issued and no binding is authored if the provided value of 532 /// \p bindingName is non-empty and contains namespaces. 533 /// 534 /// If \p bindingStrength is <i>UsdShadeTokens->fallbackStrength</i>, the 535 /// value UsdShadeTokens->weakerThanDescendants is authored sparsely, i.e. 536 /// only when there is an existing binding with a different bindingStrength. 537 /// To stamp out the bindingStrength value explicitly, clients can pass in 538 /// UsdShadeTokens->weakerThanDescendants or 539 /// UsdShadeTokens->strongerThanDescendants directly. 540 /// 541 /// If \p materialPurpose is specified and isn't equal to 542 /// UsdShadeTokens->allPurpose, the binding only applies to the specified 543 /// material purpose. 544 /// 545 /// Note that UsdShadeMaterialBindingAPI is a SingleAppliedAPI schema which 546 /// when applied updates the prim definition accordingly. This information 547 /// on the prim definition is helpful in multiple queries and more 548 /// performant. Hence its recommended to call 549 /// UsdShadeMaterialBindingAPI::Apply() when Binding a material. 550 /// 551 /// Returns true on success, false otherwise. 552 USDSHADE_API 553 bool Bind( 554 const UsdCollectionAPI &collection, 555 const UsdShadeMaterial &material, 556 const TfToken &bindingName=TfToken(), 557 const TfToken &bindingStrength=UsdShadeTokens->fallbackStrength, 558 const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const; 559 560 /// Unbinds the direct binding for the given material purpose 561 /// (\p materialPurpose) on this prim. It accomplishes this by blocking 562 /// the targets of the binding relationship in the current edit target. 563 USDSHADE_API 564 bool UnbindDirectBinding( 565 const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const; 566 567 /// Unbinds the collection-based binding with the given \p bindingName, for 568 /// the given \p materialPurpose on this prim. It accomplishes this by 569 /// blocking the targets of the associated binding relationship in the 570 /// current edit target. 571 USDSHADE_API 572 bool UnbindCollectionBinding( 573 const TfToken &bindingName, 574 const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const; 575 576 /// Unbinds all direct and collection-based bindings on this prim. 577 USDSHADE_API 578 bool UnbindAllBindings() const; 579 580 /// Removes the specified \p prim from the collection targeted by the 581 /// binding relationship corresponding to given \p bindingName and 582 /// \p materialPurpose. 583 /// 584 /// If the collection-binding relationship doesn't exist or if the 585 /// targeted collection does not include the \p prim, then this does 586 /// nothing and returns true. 587 /// 588 /// If the targeted collection includes \p prim, then this modifies the 589 /// collection by removing the prim from it (by invoking 590 /// UsdCollectionAPI::RemovePrim()). This method can be used in conjunction 591 /// with the Unbind*() methods (if desired) to guarantee that a prim 592 /// has no resolved material binding. 593 USDSHADE_API 594 bool RemovePrimFromBindingCollection( 595 const UsdPrim &prim, 596 const TfToken &bindingName, 597 const TfToken &materialPurpose) const; 598 599 /// Adds the specified \p prim to the collection targeted by the 600 /// binding relationship corresponding to given \p bindingName and 601 /// \p materialPurpose. 602 /// 603 /// If the collection-binding relationship doesn't exist or if the 604 /// targeted collection already includes the \p prim, then this does 605 /// nothing and returns true. 606 /// 607 /// If the targeted collection does not include \p prim (or excludes it 608 /// explicitly), then this modifies the collection by adding the prim to it 609 /// (by invoking UsdCollectionAPI::AddPrim()). 610 USDSHADE_API 611 bool AddPrimToBindingCollection( 612 const UsdPrim &prim, 613 const TfToken &bindingName, 614 const TfToken &materialPurpose) const; 615 616 /// @} 617 618 /// \anchor UsdShadeMaterialBindingAPI_MaterialResolution 619 /// \name Bound Material Resolution 620 /// 621 /// Material resolution is the process of determining the final bound 622 /// material for a given gprim (or UsdGeomSubset), for a given value of 623 /// material purpose. It involves examining all the bindings on the prim 624 /// and its ancestors, until a matching binding is found. The following 625 /// set of rules are applied in the process: 626 /// <ul> 627 /// <li>[1] Material bindings are inherited down the namespace chain. 628 /// Bindings lower in namespace (closer to leaf gprims) are stronger than 629 /// bindings on ancestors, unless they have their binding-strength set to 630 /// <i>UsdShadeTokens->strongerThanDescendants</i>.</li> 631 /// <li>[2] A collection binding only applies to members of the collection 632 /// that are at or beneath the prim owning the binding relationship.</li> 633 /// <li>[3] The purpose of the resolved material binding must either match 634 /// the requested special (i.e. restricted) purpose or be an all-purpose 635 /// binding. The restricted purpose binding, if available is preferred over 636 /// an all-purpose binding. 637 /// <li>[4] At any given prim, the collection-based bindings are considered 638 /// to be stronger than the direct bindings. This reflects our belief that 639 /// the combination would appear primarily to define a "fallback" material 640 /// to be used by any child prims that are not targeted by a more specific 641 /// assignment</li> 642 /// <li>[5] Collection-based binding relationships are applied in native 643 /// property order, with the earlier ordered binding relationships being 644 /// stronger.</li> 645 /// <li>[6] The "namespace specificity" with which a prim is included in a 646 /// collection is irrelevant to the binding strength of the collection. For 647 /// example, if a prim contains the ordered collection bindings 648 /// material:binding:collection:metalBits and 649 /// material:binding:collection:plasticBits, each of which targets a 650 /// collection of the same name, then if metalBits includes </Chair/Back>, 651 /// while plasticBits includes </Chair/Back/Brace/Rivet>, the binding for 652 /// </Chair/Back/Brace/Rivet> will be metalBits, because the metalBits 653 /// collection is bound more strongly than the plasticBits, and includes 654 /// an ancestor of </Chair/Back/Brace/Rivet>. 655 /// </li> 656 /// </ul> 657 /// 658 /// \note If a material binding relationship is a built-in property defined 659 /// as part of a typed prim schema, a fallback value should not be provided 660 /// for it. This is because the "material resolution" algorithm only 661 /// conisders <i>authored</i> properties. 662 /// 663 /// @{ 664 665 /// An unordered list of collection paths mapped to the associated 666 /// collection's MembershipQuery object. This is used to cache the 667 /// MembershipQuery objects for collections that are encountered during 668 /// binding resolution for a tree of prims. 669 using CollectionQueryCache = 670 tbb::concurrent_unordered_map<SdfPath, 671 std::unique_ptr<UsdCollectionAPI::MembershipQuery>, SdfPath::Hash>; 672 673 /// Alias for a unique_ptr to a DirectBinding object. 674 using DirectBindingPtr = std::unique_ptr<DirectBinding>; 675 676 struct BindingsAtPrim { 677 /// Inspects all the material:binding* properties on the \p prim and 678 /// computes direct and collection-based bindings for the given 679 /// value of \p materialPurpose. 680 USDSHADE_API 681 BindingsAtPrim(const UsdPrim &prim, const TfToken &materialPurpose); 682 683 /// If the prim has a restricted purpose direct binding, then it is 684 /// stored here. If there is no restricted purpose binding on the prim, 685 /// then the all-purpose direct binding is stored. 686 DirectBindingPtr directBinding; 687 688 /// The ordered list of restricted-purpose collection bindings on the 689 /// prim. 690 CollectionBindingVector restrictedPurposeCollBindings; 691 692 /// The ordered list of all-purpose collection bindings on the prim. 693 CollectionBindingVector allPurposeCollBindings; 694 }; 695 696 /// BindingsAtPrim needs to invoke private _GetCollectionBindings(). 697 friend struct BindingsAtPrim; 698 699 /// An unordered list of prim-paths mapped to the corresponding set of 700 /// bindings at the associated prim. This is used when computing resolved 701 /// bindings to avoid redundant computations for the shared ancestor 702 /// prims and to re-use the computed results for leaf prims. 703 using BindingsCache = tbb::concurrent_unordered_map<SdfPath, 704 std::unique_ptr<BindingsAtPrim>, SdfPath::Hash>; 705 706 /// \overload 707 /// Computes the resolved bound material for this prim, for the given 708 /// material purpose. 709 /// 710 /// This overload of ComputeBoundMaterial makes use of the BindingsCache 711 /// (\p bindingsCache) and CollectionQueryCache (\p collectionQueryCache) 712 /// that are passed in, to avoid redundant binding computations and 713 /// computations of MembershipQuery objects for collections. 714 /// It would be beneficial to make use of these when resolving bindings for 715 /// a tree of prims. These caches are populated lazily as more and more 716 /// bindings are resolved. 717 /// 718 /// When the goal is to compute the bound material for a range (or list) of 719 /// prims, it is recommended to use this version of ComputeBoundMaterial(). 720 /// Here's how you could compute the bindings of a range of prims 721 /// efficiently in C++: 722 /// 723 /// \code 724 /// std::vector<std::pair<UsdPrim, UsdShadeMaterial> primBindings; 725 /// UsdShadeMaterialBindingAPI::BindingsCache bindingsCache; 726 /// UsdShadeMaterialBindingAPI::CollectionQueryCache collQueryCache; 727 /// 728 /// for (auto prim : UsdPrimRange(rootPrim)) { 729 /// UsdShadeMaterial boundMaterial = 730 /// UsdShadeMaterialBindingAPI(prim).ComputeBoundMaterial( 731 /// &bindingsCache, &collQueryCache); 732 /// if (boundMaterial) { 733 /// primBindings.emplace_back({prim, boundMaterial}); 734 /// } 735 /// } 736 /// \endcode 737 /// 738 /// If \p bindingRel is not null, then it is set to the "winning" binding 739 /// relationship. 740 /// 741 /// See \ref UsdShadeMaterialBindingAPI_MaterialResolution "Bound Material Resolution" 742 /// for details on the material resolution process. 743 /// 744 /// The python version of this method returns a tuple containing the 745 /// bound material and the "winning" binding relationship. 746 USDSHADE_API 747 UsdShadeMaterial ComputeBoundMaterial( 748 BindingsCache *bindingsCache, 749 CollectionQueryCache *collectionQueryCache, 750 const TfToken &materialPurpose=UsdShadeTokens->allPurpose, 751 UsdRelationship *bindingRel=nullptr) const; 752 753 /// \overload 754 /// Computes the resolved bound material for this prim, for the given 755 /// material purpose. 756 /// 757 /// This overload does not utilize cached MembershipQuery object. However, 758 /// it only computes the MembershipQuery of every collection that bound 759 /// in the ancestor chain at most once. 760 /// 761 /// If \p bindingRel is not null, then it is set to the winning binding 762 /// relationship. 763 /// 764 /// See \ref UsdShadeMaterialBindingAPI_MaterialResolution "Bound Material Resolution" 765 /// for details on the material resolution process. 766 /// 767 /// The python version of this method returns a tuple containing the 768 /// bound material and the "winning" binding relationship. 769 USDSHADE_API 770 UsdShadeMaterial ComputeBoundMaterial( 771 const TfToken &materialPurpose=UsdShadeTokens->allPurpose, 772 UsdRelationship *bindingRel=nullptr) const; 773 774 /// Static API for efficiently and concurrently computing the resolved 775 /// material bindings for a vector of UsdPrims, \p prims for the 776 /// given \p materialPurpose. 777 /// 778 /// The size of the returned vector always matches the size of the input 779 /// vector, \p prims. If a prim is not bound to any material, an invalid 780 /// or empty UsdShadeMaterial is returned at the index corresponding to it. 781 /// 782 /// If the pointer \p bindingRels points to a valid vector, then it is 783 /// populated with the set of all "winning" binding relationships. 784 /// 785 /// The python version of this method returns a tuple containing two lists - 786 /// the bound materials and the corresponding "winning" binding 787 /// relationships. 788 USDSHADE_API 789 static std::vector<UsdShadeMaterial> ComputeBoundMaterials( 790 const std::vector<UsdPrim> &prims, 791 const TfToken &materialPurpose=UsdShadeTokens->allPurpose, 792 std::vector<UsdRelationship> *bindingRels=nullptr); 793 794 /// @} 795 796 // --------------------------------------------------------------------- // 797 /// \anchor UsdShadeMaterialBindingAPI_Subsets 798 /// \name Binding materials to subsets 799 /// 800 /// API to create, access and query the presence of GeomSubsets that are 801 /// created for the purpose of binding materials. 802 /// 803 /// \note GeomSubsets can only be created on valid UsdGeomImageable prims. 804 /// Hence, this API only works when the prim held by the MaterialBindingAPI 805 /// schema object is an imageable prim. 806 /// 807 /// \note Material bindings authored on GeomSubsets are honored by renderers 808 /// only if their familyName is <b>UsdShadeTokens->materialBind</b>. This 809 /// allows robust interchange of subset bindings between multiple DCC apps. 810 /// 811 /// \note The family type of the <i>materialBind</i> family of subsets 812 /// defaults to UsdGeomTokens->nonOverlapping. It can be set to 813 /// UsdGeomTokens->partition, using the API 814 /// SetMaterialBindFaceSubsetsFamilyType(). It should never be set to 815 /// UsdGeomTokens->unrestricted, since it is invalid for a piece of 816 /// geometry to be bound to multiple materials. 817 /// 818 /// Here's some sample code that shows how to create "face" subsets and 819 /// and bind materials to them. 820 /// \code 821 /// // Get the imageable prim under which subsets must be created and 822 /// // bound. 823 /// UsdGeomImageable mesh = UsdGeomImageable::Get(stage, 824 /// SdfPath("/path/to/meshPrim"); 825 /// 826 /// // Get the materials to bind to. 827 /// UsdShadeMaterial plastic = UsdShadeMaterial::Get(stage, 828 /// SdfPath("/path/to/PlasticMaterial"); 829 /// UsdShadeMaterial metal = UsdShadeMaterial::Get(stage, 830 /// SdfPath("/path/to/MetalMaterial"); 831 /// 832 /// VtIntArray plasticFaces, metalFaces; 833 /// //.. populate faceIndices here. 834 /// //.. 835 /// 836 /// UsdGeomMaterialBindingAPI meshBindingAPI(mesh.GetPrim()); 837 /// UsdGeomSubset plasticSubset = meshBindingAPI.CreateMaterialBindSubset( 838 /// "plasticSubset", plasticFaces); 839 /// UsdGeomSubset metalSubset = meshBindingAPI.CreateMaterialBindSubset( 840 /// "metalSubset", metalFaces); 841 /// 842 /// // Bind materials to the created geom-subsets. 843 /// UsdShadeMaterialBindingAPI(pasticSubset.GetPrim()).Bind(plastic) 844 /// UsdShadeMaterialBindingAPI(metalSubset.GetPrim()).Bind(metal) 845 /// 846 /// \endcode 847 /// @{ 848 849 /// Creates a GeomSubset named \p subsetName with element type, 850 /// \p elementType and familyName <b>materialBind<b> below this prim. 851 /// 852 /// If a GeomSubset named \p subsetName already exists, then its 853 /// "familyName" is updated to be UsdShadeTokens->materialBind and its 854 /// indices (at <i>default</i> timeCode) are updated with the provided 855 /// \p indices value before returning. 856 /// 857 /// This method forces the familyType of the "materialBind" family of 858 /// subsets to UsdGeomTokens->nonOverlapping if it's unset or explicitly set 859 /// to UsdGeomTokens->unrestricted. 860 /// 861 /// The default value \p elementType is UsdGeomTokens->face, as we expect 862 /// materials to be bound most often to subsets of faces on meshes. 863 USDSHADE_API 864 UsdGeomSubset CreateMaterialBindSubset( 865 const TfToken &subsetName, 866 const VtIntArray &indices, 867 const TfToken &elementType=UsdGeomTokens->face); 868 869 /// Returns all the existing GeomSubsets with 870 /// familyName=UsdShadeTokens->materialBind below this prim. 871 USDSHADE_API 872 std::vector<UsdGeomSubset> GetMaterialBindSubsets(); 873 874 /// Author the <i>familyType</i> of the "materialBind" family of GeomSubsets 875 /// on this prim. 876 /// 877 /// The default \p familyType is <i>UsdGeomTokens->nonOverlapping<i>. It 878 /// can be set to <i>UsdGeomTokens->partition</i> to indicate that the 879 /// entire imageable prim is included in the union of all the "materialBind" 880 /// subsets. The family type should never be set to 881 /// UsdGeomTokens->unrestricted, since it is invalid for a single piece 882 /// of geometry (in this case, a subset) to be bound to more than one 883 /// material. Hence, a coding error is issued if \p familyType is 884 /// UsdGeomTokens->unrestricted. 885 /// 886 /// \sa UsdGeomSubset::SetFamilyType 887 USDSHADE_API 888 bool SetMaterialBindSubsetsFamilyType(const TfToken &familyType); 889 890 /// Returns the familyType of the family of "materialBind" GeomSubsets on 891 /// this prim. 892 /// 893 /// By default, materialBind subsets have familyType="nonOverlapping", but 894 /// they can also be tagged as a "partition", using 895 /// SetMaterialBindFaceSubsetsFamilyType(). 896 /// 897 /// \sa UsdGeomSubset::GetFamilyNameAttr 898 USDSHADE_API 899 TfToken GetMaterialBindSubsetsFamilyType(); 900 901 /// Test whether a given \p name contains the "material:binding:" prefix 902 /// 903 USDSHADE_API 904 static bool CanContainPropertyName(const TfToken &name); 905 906 /// @} 907 908 private: 909 910 UsdRelationship _CreateDirectBindingRel( 911 const TfToken &materialPurpose) const; 912 913 UsdRelationship _CreateCollectionBindingRel( 914 const TfToken &bindingName, 915 const TfToken &materialPurpose) const; 916 917 // Helper method for getting collection bindings when the set of all 918 // collection binding relationship names for the required purpose is 919 // known. 920 CollectionBindingVector _GetCollectionBindings( 921 const TfTokenVector &collBindingPropertyNames) const; 922 }; 923 924 PXR_NAMESPACE_CLOSE_SCOPE 925 926 #endif 927