def test_AncestorAndPlugConfiguredTypedSchema(self): stage = Usd.Stage.CreateInMemory() # Test a type which imparts connectableAPIBehavior through its plug # metadata and not having an explicit behavior registered. self.assertTrue( UsdShade.ConnectableAPI.HasConnectableAPI( _SchemaTypeFindByName("UsdShadeTestPlugConfiguredType"))) usdShadeTestPlugConfiguredType = \ stage.DefinePrim("/UsdShadeTestPlugConfiguredType", "UsdShadeTestPlugConfiguredType") connectable = UsdShade.ConnectableAPI(usdShadeTestPlugConfiguredType) self.assertTrue(connectable) self.assertFalse(connectable.IsContainer()) self.assertFalse(connectable.RequiresEncapsulation()) # Test a type which imparts connectableAPIBehavior through its ancestor self.assertTrue( UsdShade.ConnectableAPI.HasConnectableAPI( _SchemaTypeFindByName("UsdShadeTestAncestorConfiguredType"))) usdShadeTestAncestorConfiguredType = \ stage.DefinePrim("/UsdShadeTestAncestorConfiguredType", "UsdShadeTestAncestorConfiguredType") connectable2 = UsdShade.ConnectableAPI( usdShadeTestAncestorConfiguredType) self.assertTrue(connectable2) self.assertTrue(connectable2.IsContainer()) self.assertTrue(connectable2.RequiresEncapsulation())
def test_AppliedSchemaWithDefaultBehavior(self): stage = Usd.Stage.CreateInMemory() # imparts connectability traits to UsdShadeTestTyped prim while still # having no connectability trails on the type itself. self.assertFalse(UsdShade.ConnectableAPI.HasConnectableAPI( _SchemaTypeFindByName('UsdShadeTestTyped'))) usdShadeTestTyped = stage.DefinePrim("/UsdShadeTestTyped", "UsdShadeTestTyped") usdShadeTestTypedConn = UsdShade.ConnectableAPI(usdShadeTestTyped) self.assertFalse(usdShadeTestTypedConn) self.assertFalse(usdShadeTestTypedConn.RequiresEncapsulation()) usdShadeTestTyped.AddAppliedSchema("DefaultConnectableBehaviorAPI") self.assertTrue(usdShadeTestTypedConn) self.assertTrue(usdShadeTestTypedConn.RequiresEncapsulation()) self.assertFalse(UsdShade.ConnectableAPI.HasConnectableAPI( _SchemaTypeFindByName('UsdShadeTestTyped'))) # modify/override connectability behavior for an already connectable # type material = UsdShade.Material.Define(stage, '/Mat') materialPrim = material.GetPrim() materialPrimConn = UsdShade.ConnectableAPI(materialPrim) self.assertTrue(materialPrimConn) self.assertTrue(materialPrimConn.IsContainer()) # Apply overriding connectablility behavior (default has Container as # false) materialPrim.AddAppliedSchema("DefaultConnectableBehaviorAPI") # Following should also call GetBehavior and updating the registered # behavior for this material Prim self.assertTrue(materialPrimConn) self.assertFalse(materialPrimConn.IsContainer())
def test_InvalidAppliedSchemaWithDefaultBehavior(self): stage = Usd.Stage.CreateInMemory() # create a typeless prim, add a multi-apply schema multiAPIPrim = stage.DefinePrim("/PrimA") self.assertEqual(multiAPIPrim.GetTypeName(), "") Usd.CollectionAPI.Apply(multiAPIPrim, "fanciness") connectableMultiAPIPrim = UsdShade.ConnectableAPI(multiAPIPrim) self.assertFalse(connectableMultiAPIPrim) self.assertFalse(connectableMultiAPIPrim.IsContainer()) # create a typeless prim, add a non-existent API Schema invalidAPIPrim = stage.DefinePrim("/PrimB") self.assertEqual(invalidAPIPrim.GetTypeName(), "") invalidAPIPrim.AddAppliedSchema("NoSuchLuckInvalidAPISchemaAPI") connectableInvalidAPIPrim = UsdShade.ConnectableAPI(invalidAPIPrim) self.assertFalse(connectableInvalidAPIPrim) self.assertFalse(connectableInvalidAPIPrim.IsContainer()) # create a typeless prim, add a typed schema as an API Schema! typedAPIPrim = stage.DefinePrim("/PrimC") self.assertEqual(typedAPIPrim.GetTypeName(), "") typedAPIPrim.AddAppliedSchema("Material") connectableTypedAPIPrim = UsdShade.ConnectableAPI(typedAPIPrim) self.assertFalse(connectableTypedAPIPrim) self.assertFalse(connectableTypedAPIPrim.IsContainer())
def testInstancedGeom(self): """Tests that different shader bindings are correctly authored on instanced geometry.""" worldPath = "/World" # Where collections are authored redMat = "/World/Looks/blinn1SG" redPaths = ["/World/redCube", "/World/redSphere"] blueMat = "/World/Looks/phong1SG" bluePaths = [ "/World/blueCube", "/World/blueSphere", "/World/blueSphere2"] instanceMasters = [ "/InstanceSources/World_redSphere_blueSphereMultiAssignShape", "/InstanceSources/World_blueCube_blueCubeShape"] for path in redPaths: prim = self._simpleStage.GetPrimAtPath(path) self.assertTrue(prim.IsInstance()) bindingAPI = UsdShade.MaterialBindingAPI(prim) mat, rel = bindingAPI.ComputeBoundMaterial() self.assertEqual(mat.GetPath(), redMat) self.assertEqual(rel.GetPrim().GetPath(), worldPath) for path in bluePaths: prim = self._simpleStage.GetPrimAtPath(path) self.assertTrue(prim.IsInstance()) bindingAPI = UsdShade.MaterialBindingAPI(prim) mat, rel = bindingAPI.ComputeBoundMaterial() self.assertEqual(mat.GetPath(), blueMat) self.assertEqual(rel.GetPrim().GetPath(), worldPath) for path in instanceMasters: prim = self._simpleStage.GetPrimAtPath(path) self.assertTrue(prim) self.assertFalse( prim.HasRelationship(UsdShade.Tokens.materialBinding))
def test_AppliedSchemaWithOverridingPlugMetadata(self): stage = Usd.Stage.CreateInMemory() # imparts connectability traits to UsdShadeTestTyped prim while still # having no connectability trails on the type itself. self.assertFalse( UsdShade.ConnectableAPI.HasConnectableAPI( _SchemaTypeFindByName('UsdShadeTestTyped'))) usdShadeTestTyped = stage.DefinePrim("/UsdShadeTestTyped", "UsdShadeTestTyped") connectable = UsdShade.ConnectableAPI(usdShadeTestTyped) self.assertFalse(connectable) self.assertFalse(connectable.RequiresEncapsulation()) # Add ModifiedDefaultConnectableBehaviorAPI apiSchema and see if # appropriate connectable behavior gets set for this prim usdShadeTestTyped.AddAppliedSchema( "ModifiedDefaultConnectableBehaviorAPI") self.assertTrue(connectable) self.assertTrue(connectable.IsContainer()) self.assertFalse(connectable.RequiresEncapsulation()) self.assertFalse( UsdShade.ConnectableAPI.HasConnectableAPI( _SchemaTypeFindByName('UsdShadeTestTyped'))) # If multiple applied schemas provide connectableBehavior then the order # in which these get applied determines what drives the prim's # connectable behavior # Also apply the DefaultConnectableBehaviorAPI, connectableBehavior # still should remain the same that is the one specified by # ModifiedDefaultConnectableBehaviorAPI usdShadeTestTyped.AddAppliedSchema("DefaultConnectableBehaviorAPI") self.assertTrue(connectable) self.assertTrue(connectable.IsContainer()) self.assertFalse(connectable.RequiresEncapsulation()) # Does ModifiedDefaultConnectableBehaviorAPI when explicit applied # modify the behavior of a UsdShadeMaterial and UsdShadeShader prim material = UsdShade.Material.Define(stage, '/Mat') materialPrim = material.GetPrim() materialPrimConn = UsdShade.ConnectableAPI(materialPrim) self.assertTrue(materialPrimConn) self.assertTrue(materialPrimConn.IsContainer()) self.assertTrue(materialPrimConn.RequiresEncapsulation()) # Apply overriding ModifiedDefaultConnectableBehaviorAPI materialPrim.AddAppliedSchema("ModifiedDefaultConnectableBehaviorAPI") self.assertTrue(materialPrimConn.IsContainer()) self.assertFalse(materialPrimConn.RequiresEncapsulation()) shader = UsdShade.Shader.Define(stage, '/Shader') shaderPrim = shader.GetPrim() shaderPrimConn = UsdShade.ConnectableAPI(shaderPrim) self.assertTrue(shaderPrimConn) self.assertFalse(shaderPrimConn.IsContainer()) self.assertTrue(shaderPrimConn.RequiresEncapsulation()) # Apply overriding ModifiedDefaultConnectableBehaviorAPI shaderPrim.AddAppliedSchema("ModifiedDefaultConnectableBehaviorAPI") self.assertTrue(shaderPrimConn.IsContainer()) self.assertFalse(shaderPrimConn.RequiresEncapsulation())
def _updateMeshBinding(path, appController): s = appController._dataModel.stage l = s.GetSessionLayer() s.SetEditTarget(l) mesh = s.GetPrimAtPath('/Scene/Geom/Plane') material = UsdShade.Material(s.GetPrimAtPath(path)) UsdShade.MaterialBindingAPI(mesh).Bind(material)
def read_usd_material(cls, material, texture_path, time=None): r"""Read USD material and return a Material object. The shader used must have a corresponding registered reader function. If no available reader is found, the material parameters will be returned as a dictionary. Args: material (UsdShade.Material): Valid USD Material prim texture_path (str, optional): Path to textures directory. If the USD has absolute paths to textures, set to an empty string. By default, the textures will be assumed to be under the same directory as the USD specified by `file_path`. time (convertible to float, optional): Positive integer indicating the time at which to retrieve parameters. Returns: (Material): Material object determined by the corresponding reader function. """ if time is None: time = Usd.TimeCode.Default() if not UsdShade.Material(material): raise MaterialLoadError( f'The material `{material}` is not a valid UsdShade.Material object.' ) for surface_output in material.GetSurfaceOutputs(): if not surface_output.HasConnectedSource(): continue surface_shader = surface_output.GetConnectedSource()[0] shader = UsdShade.Shader(surface_shader) if not UsdShade.Shader(shader): raise MaterialLoadError( f'The shader `{shader}` is not a valid UsdShade.Shader object.' ) if shader.GetImplementationSourceAttr().Get(time=time) == 'id': shader_name = UsdShade.Shader(surface_shader).GetShaderId() elif shader.GetPrim().HasAttribute('info:mdl:sourceAsset'): # source_asset = shader.GetPrim().GetAttribute('info:mdl:sourceAsset').Get(time=time) shader_name = shader.GetPrim().GetAttribute( 'info:mdl:sourceAsset:subIdentifier').Get(time=time) else: shader_name = '' warnings.warn( f'A reader for the material defined by `{material}` is not yet implemented.' ) params = _get_shader_parameters(surface_shader, time) if shader_name not in cls._usd_readers: warnings.warn( 'No registered readers were able to process the material ' f'`{material}` with shader `{shader_name}`.') return params reader = cls._usd_readers[shader_name] return reader(params, texture_path, time) raise MaterialError(f'Error processing material {material}')
def add_material(materials_opt, xsi_mat, stage, stage_asset_path, usd_xform, usd_prim, is_bind=True): # do the same in prim_mesh material_asset_path = materials_opt.get("asset_path", None) if material_asset_path is not None: rel_material_path = utils.transform_path_to_relative(stage_asset_path, material_asset_path) mat_name = utils.buil_material_name(xsi_mat) mat_ref = stage.DefinePrim(str(usd_xform.GetPath()) + "/" + mat_name) mat_ref.GetReferences().AddReference(rel_material_path, "/" + xsi_mat.Library.Name + "/" + xsi_mat.Name) # bind the main material if is_bind: UsdShade.MaterialBindingAPI(usd_prim).Bind(UsdShade.Material(stage.GetPrimAtPath(mat_ref.GetPath())))
def IsConverter(self): mtlxShaderReaderTest.IsConverterCalled = True self._refinedOutputToken = '' prim = self._GetArgs().GetUsdPrim() shaderSchema = UsdShade.Shader(prim) if (not shaderSchema): return None shaderId = shaderSchema.GetIdAttr().Get() input = shaderSchema.GetInput('in') if (not input): return None (source, sourceOutputName, sourceType) = input.GetConnectedSource() if (not source): return None downstreamSchema = UsdShade.Shader(source.GetPrim()) if (not downstreamSchema): return None # No refinement necessary for ND_convert_color3_vector3 and ND_normalmap. if ("ND_luminance_" in shaderId): # Luminance is an alpha output. self._setAlphaIsLuminance = True self._refinedOutputToken = 'outAlpha' elif ("ND_swizzle_" in shaderId): channelsAttr = shaderSchema.GetInput('channels') val = channelsAttr.Get(Usd.TimeCode.Default()) if (val == 'r' or val == 'x'): self._refinedOutputToken = 'outColorR' elif (val == 'g'): self._refinedOutputToken = 'outColorG' elif (val == 'y'): if (shaderSchema.GetOutput('out').GetTypeName() == 'Float'): self._refinedOutputToken = 'outAlpha' else: self._refinedOutputToken = 'outColorG' elif (val == 'b' or val == 'z'): self._refinedOutputToken = 'outColorB' elif (val == 'a' or val == 'w'): self._refinedOutputToken = 'outAlpha' else: print("Unsupported swizzle" + val) # TF_CODING_ERROR("Unsupported swizzle"); # } else if (channels.size() == 3) { # // Triple channel swizzles must go to outColor: # self._refinedOutputToken = 'outColor'; # } self._downstreamPrim = source.GetPrim() return downstreamSchema, sourceOutputName
def testExportPxrRisShading(self): """ Tests that exporting a Maya mesh with a simple Maya shading setup results in the correct shading on the USD mesh. """ cubePrim = self._stage.GetPrimAtPath('/MarbleCube/Geom/Cube') self.assertTrue(cubePrim) # Validate the Material prim bound to the Mesh prim. materialBindingAPI = UsdShade.MaterialBindingAPI(cubePrim) material = materialBindingAPI.ComputeBoundMaterial()[0] self.assertTrue(material) materialPath = material.GetPath().pathString self.assertEqual(materialPath, '/MarbleCube/Materials/MarbleCubeSG') if Usd.GetVersion() >= (0, 21, 5): # For USD 21.05 and later, GetInputs() and GetOutputs() take an # "onlyAuthored" argument that is True by default, so in that case # we expect only one output on the material for the "surface" # terminal in the "ri" renderContext that the export should have # authored. expectedNumOutputs = 1 else: # Otherwise prior to USD 21.05, GetInputs() and GetOutputs() did # not take any arguments and always included the built-in # terminals for the universal renderContext as well as any other # authored terminals. expectedNumOutputs = 4 # Validate the surface shader that is connected to the material. materialOutputs = material.GetOutputs() self.assertEqual(len(materialOutputs), expectedNumOutputs) print(self._stage.ExportToString()) materialOutput = material.GetOutput('ri:surface') (connectableAPI, outputName, outputType) = materialOutput.GetConnectedSource() self.assertEqual(outputName, 'out') shader = UsdShade.Shader(connectableAPI) self.assertTrue(shader) shaderId = shader.GetIdAttr().Get() self.assertEqual(shaderId, 'PxrMayaMarble') # Validate the connected input on the surface shader. shaderInput = shader.GetInput('placementMatrix') self.assertTrue(shaderInput) (connectableAPI, outputName, outputType) = shaderInput.GetConnectedSource() self.assertEqual(outputName, 'worldInverseMatrix') shader = UsdShade.Shader(connectableAPI) self.assertTrue(shader) shaderId = shader.GetIdAttr().Get() self.assertEqual(shaderId, 'PxrMayaPlacement3d')
def CheckPrim(self, prim): from pxr import UsdGeom, UsdShade parent = prim.GetParent() # Of course we must allow Boundables under other Boundables, so that # schemas like UsdGeom.Pointinstancer can nest their prototypes. But # we disallow a PointInstancer under a Mesh just as we disallow a Mesh # under a Mesh, for the same reason: we cannot then independently # adjust visibility for the two objects, nor can we reasonably compute # the parent Mesh's extent. if prim.IsA(UsdGeom.Boundable): if parent: if self._HasGprimAncestor(parent): self._AddFailedCheck( "Gprim <%s> has an ancestor prim that " "is also a Gprim, which is not allowed." % prim.GetPath()) connectable = UsdShade.ConnectableAPI(prim) # The GetTypeName() check is to work around a bug in # ConnectableAPIBehavior registry. if prim.GetTypeName() and connectable: if parent: pConnectable = UsdShade.ConnectableAPI(parent) if not parent.GetTypeName(): pConnectable = None if pConnectable and not pConnectable.IsContainer(): # XXX This should be a failure as it is a violation of the # UsdShade OM. But pragmatically, there are many # authoring tools currently producing this structure, which # does not _currently_ perturb Hydra, so we need to start # with a warning self._AddWarning("Connectable %s <%s> cannot reside " "under a non-Container Connectable %s" % (prim.GetTypeName(), prim.GetPath(), parent.GetTypeName())) elif not pConnectable: # it's only OK to have a non-connectable parent if all # the rest of your ancestors are also non-connectable. The # error message we give is targeted at the most common # infraction, using Scope or other grouping prims inside # a Container like a Material connAnstr = self._FindConnectableAncestor(parent) if connAnstr is not None: self.AddFailedCheck( "Connectable %s <%s> can only have " "Connectable Container ancestors up " "to %s ancestor <%s>, but its parent" "%s is a %s." % (prim.GetTypeName(), prim.GetPath(), connAnstr.GetTypeName(), connAnstr.GetPath(), parent.GetName(), parent.GetTypeName()))
def test_BlockingOnOver(self): stage = Usd.Stage.CreateInMemory() over = stage.OverridePrim('/World/over') look = UsdShade.Material.Define(stage, "/World/Material") self.assertTrue(look) gprim = stage.DefinePrim("/World/gprim") UsdShade.MaterialBindingAPI(over).UnbindDirectBinding() UsdShade.MaterialBindingAPI.Apply(gprim).Bind(look) # This will compose in gprim's binding, but should still be blocked over.GetInherits().AddInherit("/World/gprim") self.assertFalse(UsdShade.MaterialBindingAPI(over).ComputeBoundMaterial()[0])
def testExportPxrRisShading(self): """ Tests that exporting a Maya mesh with a simple Maya shading setup results in the correct shading on the USD mesh. """ cubePrim = self._stage.GetPrimAtPath('/MarbleCube/Geom/Cube') self.assertTrue(cubePrim) # Validate the Material prim bound to the Mesh prim. material = UsdShade.Material.GetBoundMaterial(cubePrim) self.assertTrue(material) materialPath = material.GetPath().pathString self.assertEqual(materialPath, '/MarbleCube/Looks/MarbleCubeSG') # Validate the surface shader that is connected to the material. # XXX: Note that the expected number of outputs here is two rather than # one, since we are still authoring the UsdRi Bxdf source in addition # to the surface terminal for backwards compatibility. When consumers # are updated to use the surface terminal instead, this test will have # to be updated. materialOutputs = material.GetOutputs() self.assertEqual(len(materialOutputs), 2) materialOutput = material.GetOutput('surface') (connectableAPI, outputName, outputType) = materialOutput.GetConnectedSource() self.assertEqual(outputName, 'out') shader = UsdShade.Shader(connectableAPI) self.assertTrue(shader) # XXX: Validate the UsdRi Bxdf. This must also be removed when we no # longer author it. from pxr import UsdRi usdRiMaterialAPI = UsdRi.MaterialAPI(material.GetPrim()) self.assertTrue(usdRiMaterialAPI) bxdf = usdRiMaterialAPI.GetBxdf() self.assertEqual(bxdf.GetPrim(), shader.GetPrim()) shaderId = shader.GetIdAttr().Get() self.assertEqual(shaderId, 'PxrMayaMarble') # Validate the connected input on the surface shader. shaderInput = shader.GetInput('placementMatrix') self.assertTrue(shaderInput) (connectableAPI, outputName, outputType) = shaderInput.GetConnectedSource() self.assertEqual(outputName, 'worldInverseMatrix') shader = UsdShade.Shader(connectableAPI) self.assertTrue(shader) shaderId = shader.GetIdAttr().Get() self.assertEqual(shaderId, 'PxrMayaPlacement3d')
def testExportRfMShaders(self): ''' Tests that exporting a Maya mesh with a simple Maya shading setup results in the correct shading on the USD mesh. ''' cubePrim = self._stage.GetPrimAtPath('/MarbleCube/Geom/Cube') self.assertTrue(cubePrim) # Validate the Material prim bound to the Mesh prim. self.assertTrue(cubePrim.HasAPI(UsdShade.MaterialBindingAPI)) materialBindingAPI = UsdShade.MaterialBindingAPI(cubePrim) material = materialBindingAPI.ComputeBoundMaterial()[0] self.assertTrue(material) materialPath = material.GetPath().pathString self.assertEqual(materialPath, '/MarbleCube/Materials/MarbleCubeSG') # We expect four outputs on the material, the three built-in terminals # for the universal renderContext, and a fourth for the "surface" # terminal in the "ri" renderContext that the export should have # authored. materialOutputs = material.GetOutputs() self.assertEqual(len(materialOutputs), 4) # Validate the lambert surface shader that is connected to the material. materialOutput = material.GetOutput('ri:surface') (connectableAPI, outputName, outputType) = materialOutput.GetConnectedSource() self.assertEqual(outputName, UsdShade.Tokens.surface) shader = UsdShade.Shader(connectableAPI) self.assertTrue(shader) shaderId = shader.GetIdAttr().Get() self.assertEqual(shaderId, 'PxrMayaLambert') # Validate the connected input on the lambert surface shader. shaderInput = shader.GetInput('color') self.assertTrue(shaderInput) (connectableAPI, outputName, outputType) = shaderInput.GetConnectedSource() self.assertEqual(outputName, 'outColor') shader = UsdShade.Shader(connectableAPI) self.assertTrue(shader) shaderId = shader.GetIdAttr().Get() self.assertEqual(shaderId, 'PxrMayaMarble') # Validate the connected input on the marble shader. shaderInput = shader.GetInput('placementMatrix') self.assertTrue(shaderInput) (connectableAPI, outputName, outputType) = shaderInput.GetConnectedSource() self.assertEqual(outputName, 'worldInverseMatrix') shader = UsdShade.Shader(connectableAPI) self.assertTrue(shader) shaderId = shader.GetIdAttr().Get() self.assertEqual(shaderId, 'PxrMayaPlacement3d')
def testNestedInstancedGeom(self): """Tests that different shader bindings are correctly authored on instanced geometry within nested instances.""" worldPath = "/World" # Where collections are authored greenMat = "/World/Materials/blinn1SG" greenPaths = [ "/World/SimpleInstance1/Shape", "/World/ComplexA/NestedA/Base1/BaseShape1", "/World/ComplexA/NestedB/Base1/BaseShape1", "/World/Extra/Base3/Shape", "/World/ComplexB/NestedA/Base1/BaseShape1", "/World/ComplexB/NestedB/Base1/BaseShape1" ] blueMat = "/World/Materials/blinn2SG" bluePaths = [ "/World/SimpleInstance2/Shape", "/World/ComplexA/NestedA/Base2/BaseShape1", "/World/ComplexA/NestedB/Base2/BaseShape1", "/World/ComplexB/NestedA/Base2/BaseShape1", "/World/ComplexB/NestedB/Base2/BaseShape1" ] instanceMasters = [ "/InstanceSources/World_ComplexA_NestedA_Base1_BaseShape1" + "/Shape", "/InstanceSources/World_SimpleInstance1_SimpleInstanceShape1" + "/Shape" ] for path in greenPaths: prim = self._nestedStage.GetPrimAtPath(path) self.assertTrue(prim, msg=path) self.assertTrue(prim.IsInstanceProxy()) bindingAPI = UsdShade.MaterialBindingAPI(prim) mat, rel = bindingAPI.ComputeBoundMaterial() self.assertEqual(mat.GetPath(), greenMat) self.assertEqual(rel.GetPrim().GetPath(), worldPath) for path in bluePaths: prim = self._nestedStage.GetPrimAtPath(path) self.assertTrue(prim, msg=path) self.assertTrue(prim.IsInstanceProxy()) bindingAPI = UsdShade.MaterialBindingAPI(prim) mat, rel = bindingAPI.ComputeBoundMaterial() self.assertEqual(mat.GetPath(), blueMat) self.assertEqual(rel.GetPrim().GetPath(), worldPath) for path in instanceMasters: prim = self._nestedStage.GetPrimAtPath(path) self.assertTrue(prim) self.assertFalse( prim.HasRelationship(UsdShade.Tokens.materialBinding))
def testExportDisplacementShaders(self): ''' Tests that exporting multiple Maya planes with varying displacement setups results in the expected USD data: ''' textures = ["RGBA", "RGB", "MonoA", "Mono"] channels = ["r", "g", "b", "a", "a"] for suffix in range(1, 21): image = textures[int((suffix - 1) / 5)] channel = channels[(suffix - 1) % 5] mesh_prim = self._stage.GetPrimAtPath('/pPlane%i' % suffix) self.assertTrue(mesh_prim) # Validate the Material prim bound to the Mesh prim. self.assertTrue(mesh_prim.HasAPI(UsdShade.MaterialBindingAPI)) mat_binding = UsdShade.MaterialBindingAPI(mesh_prim) material = mat_binding.ComputeBoundMaterial()[0] self.assertTrue(material) material_path = material.GetPath().pathString self.assertEqual( material_path, '/pPlane%i/Materials/blinn%iSG' % (suffix, suffix)) self.assertTrue(material.ComputeSurfaceSource()) self.assertTrue(material.ComputeDisplacementSource()) # Validate the shader that is connected to the material. mat_out = material.GetOutput(UsdShade.Tokens.displacement) (connect_api, out_name, _) = mat_out.GetConnectedSource() self.assertEqual(out_name, UsdShade.Tokens.displacement) shader = UsdShade.Shader(connect_api) self.assertTrue(shader) shader_id = shader.GetIdAttr().Get() self.assertEqual(shader_id, 'UsdPreviewSurface') # Validate the connected input on the displacement shader. in_displacement = shader.GetInput('displacement') self.assertTrue(in_displacement) (connect_api, out_name, _) = in_displacement.GetConnectedSource() self.assertEqual(out_name, channel) shader = UsdShade.Shader(connect_api) self.assertTrue(shader) shader_id = shader.GetIdAttr().Get() self.assertEqual(shader_id, 'UsdUVTexture') filename = shader.GetInput("file") self.assertTrue(filename.Get().path.endswith("/%s.png" % image))
def test_Basic(self): s = Usd.Stage.CreateInMemory() rl = s.GetRootLayer() # set up so the weaker subtree binds gprim to look1, and # stronger subtree to look2 lw1 = UsdShade.Material.Define(s, "/weaker/look1") lw2 = UsdShade.Material.Define(s, "/weaker/look2") gpw = s.OverridePrim("/weaker/gprim") lw1.Bind(gpw) self.assertEqual( UsdShade.MaterialBindingAPI( gpw).GetDirectBindingRel().GetTargets(), [Sdf.Path("/weaker/look1")]) ls1 = UsdShade.Material.Define(s, "/stronger/look1") ls2 = UsdShade.Material.Define(s, "/stronger/look2") gps = s.OverridePrim("/stronger/gprim") ls2.Bind(gps) self.assertEqual( UsdShade.MaterialBindingAPI( gps).GetDirectBindingRel().GetTargets(), [Sdf.Path("/stronger/look2")]) cr = s.OverridePrim("/composed") cr.GetReferences().AddReference(rl.identifier, "/stronger") cr.GetReferences().AddReference(rl.identifier, "/weaker") gpc = s.GetPrimAtPath("/composed/gprim") lb = UsdShade.MaterialBindingAPI(gpc).GetDirectBindingRel() # validate we get look2, the stronger binding self.assertEqual(lb.GetTargets(), [Sdf.Path("/composed/look2")]) # upon unbinding *in* the stronger site (i.e. "/stronger/gprim"), # we should still be unbound in the fully composed view UsdShade.MaterialBindingAPI(gps).UnbindAllBindings() self.assertEqual(lb.GetTargets(), []) # but *clearing* the target on the referenced prim should allow # the weaker binding to shine through UsdShade.MaterialBindingAPI(gps).GetDirectBindingRel().ClearTargets( True) print rl.ExportToString() self.assertEqual(lb.GetTargets(), [Sdf.Path("/composed/look1")])
def _GetBoundMaterial(self, prim, materialPurpose=UsdShade.Tokens.allPurpose): (material, bindingRel) = UsdShade.MaterialBindingAPI(prim).ComputeBoundMaterial( materialPurpose) # Whenever we get a valid material, there must be a valid bindingRel. if material: self.assertTrue(bindingRel) return material
def CheckPrim(self, prim): # Right now, we find texture referenced by looking at the asset-valued # inputs on Connectable prims. from pxr import Sdf, Usd, UsdShade # Nothing to do if we are allowing all formats, or if # we are an untyped prim if self._allowedFormats is None or not prim.GetTypeName(): return # Check if the prim is Connectable. connectable = UsdShade.ConnectableAPI(prim) if not connectable: return shaderInputs = connectable.GetInputs() for ip in shaderInputs: attrPath = ip.GetAttr().GetPath() if ip.GetTypeName() == Sdf.ValueTypeNames.Asset: texFilePath = ip.Get(Usd.TimeCode.EarliestTime()) # ip may be unauthored and/or connected if texFilePath: self._CheckTexture(texFilePath.path, attrPath) elif ip.GetTypeName() == Sdf.ValueTypeNames.AssetArray: texPathArray = ip.Get(Usd.TimeCode.EarliestTime()) if texPathArray: for texPath in texPathArray: self._CheckTexture(texPath, attrPath)
def test_NewPluginRegistrationNotice(self): # Add some behavior entries self.assertTrue( UsdShade.ConnectableAPI.HasConnectableAPI( Tf.Type.FindByName('UsdShadeMaterial'))) self.assertFalse( UsdShade.ConnectableAPI.HasConnectableAPI( _SchemaTypeFindByName("UsdShadeTestTyped"))) # check a material's behavior before registering new plugins stage = Usd.Stage.CreateInMemory() material = UsdShade.Material.Define(stage, "/Mat") matConnectable = UsdShade.ConnectableAPI(material) self.assertTrue(matConnectable) self.assertTrue(matConnectable.IsContainer()) # register new plugins, to trigger a call to _DidRegisterPlugins, which # should prune the behavior cache off any entry which has a null # behavior defined pr = Plug.Registry() testPlugins = pr.RegisterPlugins(os.path.abspath("resources/plugins2")) self.assertTrue(len(testPlugins) == 1) # check material connectableAPI again if it has the correct behavior # still self.assertTrue(matConnectable) self.assertTrue(matConnectable.IsContainer())
def _assign_materials(obj_prim, obj, usd_mesh): usd_mat = None if obj.material_slots and obj.material_slots[0].material: usd_mat = material.sync(obj_prim, obj.material_slots[0].material, obj) if usd_mat: UsdShade.MaterialBindingAPI(usd_mesh).Bind(usd_mat)
def test_ShaderProperties(self): """ Test property correctness on the "TestShaderPropertiesNodeUSD" node. See shaderParserTestUtils TestShaderPropertiesNode method for detailed description of the test. """ stage = Usd.Stage.Open('shaderDefs.usda') shaderDef = UsdShade.Shader.Get(stage, "/TestShaderPropertiesNodeUSD") discoveryResults = UsdShade.ShaderDefUtils.GetNodeDiscoveryResults( shaderDef, stage.GetRootLayer().realPath) self.assertEqual(len(discoveryResults), 1) discoveryResult = discoveryResults[0] node = UsdShade.ShaderDefParserPlugin().Parse(discoveryResult) assert node is not None self.assertEqual(os.path.basename(node.GetResolvedImplementationURI()), "TestShaderPropertiesNode.glslfx") self.assertEqual(os.path.basename(node.GetResolvedDefinitionURI()), "shaderDefs.usda") utils.TestShaderPropertiesNode(node)
def testShaderAttrsAuthoredSparsely(self): """ Tests that only the attributes authored in Maya are exported to USD. """ shaderPrimPath = '/MarbleCube/Looks/MarbleCubeSG/MarbleShader' shaderPrim = self._stage.GetPrimAtPath(shaderPrimPath) self.assertTrue(shaderPrim) shader = UsdShade.Shader(shaderPrim) self.assertTrue(shader) shaderId = shader.GetIdAttr().Get() self.assertEqual(shaderId, 'PxrMayaMarble') shaderInputs = shader.GetInputs() self.assertEqual(len(shaderInputs), 3) inputOutAlpha = shader.GetInput('outAlpha').Get() self.assertTrue(Gf.IsClose(inputOutAlpha, 0.0894, 1e-6)) inputOutColor = shader.GetInput('outColor').Get() self.assertTrue(Gf.IsClose(inputOutColor, Gf.Vec3f(0.298, 0.0, 0.0), 1e-6)) inputPlacementMatrix = shader.GetInput('placementMatrix') (connectableAPI, outputName, outputType) = inputPlacementMatrix.GetConnectedSource() self.assertEqual(connectableAPI.GetPath().pathString, '/MarbleCube/Looks/MarbleCubeSG/MarbleCubePlace3dTexture') shaderOutputs = shader.GetOutputs() self.assertEqual(len(shaderOutputs), 1)
def testShaderAttrsAuthoredSparsely(self): """ Tests that only the attributes authored in Maya are exported to USD. """ shaderPrimPath = '/MarbleCube/Materials/MarbleCubeSG/MarbleShader' shaderPrim = self._stage.GetPrimAtPath(shaderPrimPath) self.assertTrue(shaderPrim) shader = UsdShade.Shader(shaderPrim) self.assertTrue(shader) shaderId = shader.GetIdAttr().Get() self.assertEqual(shaderId, 'PxrMayaMarble') shaderInputs = shader.GetInputs() self.assertEqual(len(shaderInputs), 1) inputPlacementMatrix = shader.GetInput('placementMatrix') (connectableAPI, outputName, outputType) = inputPlacementMatrix.GetConnectedSource() self.assertEqual( connectableAPI.GetPath().pathString, '/MarbleCube/Materials/MarbleCubeSG/MarbleCubePlace3dTexture') shaderOutputs = shader.GetOutputs() self.assertEqual(len(shaderOutputs), 1)
def testExportSelfContainedPackage(self): """ Tests that the exported usdz file is self contained, such that it's valid for AR QuickLook on iOS """ maya_file = os.path.join(self.temp_dir, "UsdExportPackage", "asset.ma") cmds.file(maya_file, force=True, open=True) # Write the file out path = os.path.join(self.temp_dir, 'testExportSelfContainedPackage.usdz') cmds.mayaUSDExport(f=path, compatibility='appleArKit') # Check with USD what the path to the texture is stage = Usd.Stage.Open(path) prim = stage.GetPrimAtPath( "/AssetGroup/Looks/pxrUsdPreviewSurface1SG/file1") shader = UsdShade.Shader(prim) tex = shader.GetInput("file").Get().path # Check to see if the zipfile contains the texture with zipfile.ZipFile(path) as zf: for zfile in zf.filelist: if zfile.filename == tex: break else: self.fail("Could not find texture inside zip file")
def get_direct_bound_material_for_purpose(binding, purpose): """Find the bound material, using direct binding, if it exists. Args: binding (`pxr.UsdShade.MaterialBindingAPI`): The material binding that will be used to search for a direct binding. purpose (str): The name of some direct-binding purpose to filter by. If no name is given, any direct-binding that is found gets returned. Returns: `pxr.UsdShade.Material` or NoneType: The found material, if one could be found. """ relationship = binding.GetDirectBindingRel(materialPurpose=purpose) direct = UsdShade.MaterialBindingAPI.DirectBinding(relationship) if not direct.GetMaterial(): return None material = direct.GetMaterialPath() prim = binding.GetPrim().GetStage().GetPrimAtPath(material) if not prim.IsValid(): return None return UsdShade.Material(prim)
def main(): """Run the main execution of the current script.""" stage = Usd.Stage.CreateInMemory() UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.y) root = UsdGeom.Xform.Define(stage, "/TexModel") Usd.ModelAPI(root).SetKind(Kind.Tokens.component) billboard = attach_billboard(stage, root) material = UsdShade.Material.Define( stage, str(billboard.GetPath()) + "/" + "boardMat") shader = attach_surface_shader(stage, material, str(material.GetPath()) + "/" + "PBRShader") reader = attach_texture(stage, shader, str(material.GetPath())) st_input = material.CreateInput("frame:stPrimvarName", Sdf.ValueTypeNames.Token) st_input.Set("st") reader.CreateInput("varname", Sdf.ValueTypeNames.Token).ConnectToSource(st_input) UsdShade.MaterialBindingAPI(billboard).Bind(material) print(stage.GetRootLayer().ExportToString())
def testUsdExportCustomConverter(self): """ Tests a custom exporter for a conversion that exists in an unloaded plugin. """ # Load test scene: file_path = os.path.join(self.input_path, "UsdExportCustomConverterTest", "testScene.ma") cmds.file(file_path, force=True, open=True) # Export to USD: usd_path = os.path.abspath('UsdExportCustomConverterTest.usda') # Using the "maya" material conversion, which only exists in the test # plugin options = ["shadingMode=useRegistry", "convertMaterialsTo=maya", "mergeTransformAndShape=1"] default_ext_setting = cmds.file(q=True, defaultExtensions=True) cmds.file(defaultExtensions=False) cmds.file(usd_path, force=True, options=";".join(options), typ="USD Export", pr=True, ea=True) cmds.file(defaultExtensions=default_ext_setting) # Make sure we have a Maya standardSurface material in the USD file: stage = Usd.Stage.Open(usd_path) material = stage.GetPrimAtPath( "/pCube1/Looks/standardSurface2SG/standardSurface2") shader = UsdShade.Shader(material) self.assertEqual(shader.GetIdAttr().Get(), "standardSurface")
def testExportStandaloneTransform2dTransformed(self): """ Test that a material with transform 2D values exports with a UsdTransform2D shader and the correct values """ root = self.stage.GetPrimAtPath( "/PxrUsdTransform2dExportTest/Looks/pxrUsdPreviewSurface_TransformedSG" ) transform = findTransformPrim(root) self.assertTrue(transform, "Missing UsdTransform2D shader") shader = UsdShade.Shader(transform) translation_input = shader.GetInput('translation') rotation_input = shader.GetInput('rotation') scale_input = shader.GetInput('scale') expected_translation_value = (0.10104963, 0.19860554) expected_rotation_value = 0.2 expected_scale_value = (0.8, 1) self.assertAlmostEqual(translation_input.Get(), expected_translation_value) self.assertAlmostEqual(rotation_input.Get(), expected_rotation_value) self.assertEqual(scale_input.Get(), expected_scale_value)
def CheckPrim(self, prim): # Right now, we find texture referenced by looking at the asset-valued # shader inputs. However, it is entirely legal to feed the "fileName" # input of a UsdUVTexture shader from a UsdPrimvarReader_string. # Hence, ideally we would also check "the right" primvars on # geometry prims here. However, identifying the right primvars is # non-trivial. We probably need to pre-analyze all the materials. # Not going to try to do this yet, but it raises an interesting # validation pattern - from pxr import Sdf, UsdShade # Check if the prim is a shader. if not prim.IsA(UsdShade.Shader): return shader = UsdShade.Shader(prim) shaderInputs = shader.GetInputs() for ip in shaderInputs: if ip.GetTypeName() == Sdf.ValueTypeNames.Asset: texFilePath = str(ip.Get()).strip('@') self._CheckTexture(texFilePath) elif ip.GetTypeName() == Sdf.ValueTypeNames.AssetArray: texPathArray = ip.Get() texPathArray = [str(i).strip('@') for i in texPathArray] for texPath in texPathArray: self._CheckTexture(texFilePath)