예제 #1
0
    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)
예제 #2
0
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.Apply(mesh).Bind(material)
예제 #3
0
    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 ValidateMaterial(stage):
            hairPrim = stage.GetPrimAtPath(
                '/ModelShading/Materials/HairMaterial')
            hairMaterial = UsdShade.Material(hairPrim)
            self.assertTrue(hairMaterial)
            wetHairSurfPath = Sdf.Path(
                '/ModelShading/Shaders/HairWetSurface.out')
            wetHairDispPath = Sdf.Path('/ModelShading/Shaders/HairWetDisp.out')
            wetHairPatternPath = Sdf.Path(
                '/ModelShading/Shaders/HairWetPattern.out')

            connectedSurface = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('surface'))
            connectedSurfacePath = connectedSurface[0].GetPath(
            ).AppendProperty(connectedSurface[1])
            self.assertEqual(connectedSurfacePath, wetHairSurfPath)

            connectedDisplacement = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('displacement'))
            connectedDisplacementPath = connectedDisplacement[0].GetPath(
            ).AppendProperty(connectedDisplacement[1])
            self.assertEqual(connectedDisplacementPath, wetHairDispPath)

            connectedPattern = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('pattern'))
            connectedPatternPath = connectedPattern[0].GetPath(
            ).AppendProperty(connectedPattern[1])
            self.assertEqual(connectedPatternPath, wetHairPatternPath)

            # change the root-level variantSet, which should in turn change the Material's
            self.assertTrue(rootPrim.GetVariantSets().SetSelection(
                "materialVariant", "Dry"))
            self.assertTrue(hairMaterial)
            dryHairSurfPath = Sdf.Path(
                '/ModelShading/Shaders/HairDrySurface.out')
            dryHairDispPath = Sdf.Path('/ModelShading/Shaders/HairDryDisp.out')
            dryHairPatternPath = Sdf.Path(
                '/ModelShading/Shaders/HairDryPattern.out')

            connectedSurface = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('surface'))
            connectedSurfacePath = connectedSurface[0].GetPath(
            ).AppendProperty(connectedSurface[1])
            self.assertEqual(connectedSurfacePath, dryHairSurfPath)

            connectedDisplacement = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('displacement'))
            connectedDisplacementPath = connectedDisplacement[0].GetPath(
            ).AppendProperty(connectedDisplacement[1])
            self.assertEqual(connectedDisplacementPath, dryHairDispPath)

            connectedPattern = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('pattern'))
            connectedPatternPath = connectedPattern[0].GetPath(
            ).AppendProperty(connectedPattern[1])
            self.assertEqual(connectedPatternPath, dryHairPatternPath)
예제 #5
0
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())))
예제 #6
0
def GetMaterialXMaterials(usdStage):
    mtlxMaterials = []
    for prim in usdStage.Traverse():
        material = UsdShade.Material(prim)
        if material:
            outputs = material.GetOutputs()
            for output in outputs:
                if output.GetBaseName() == ('mtlx:surface'):
                    mtlxMaterials.append(material)
    return mtlxMaterials
        def ValidateMaterial(stage):
            hairPath = Sdf.Path('/ModelShading/Materials/HairMaterial')
            hairPrim = stage.GetPrimAtPath(hairPath)
            hairMaterial = UsdShade.Material(hairPrim)
            self.assertTrue(hairMaterial)

            # Validate wet surface terminal connection
            wetHairSurfPath = hairPath.AppendChild('HairWetSurface')\
                                      .AppendProperty("outputs:surface")
            surfaceTerminal = hairMaterial.GetSurfaceOutput()
            self.assertTrue(surfaceTerminal.HasConnectedSource())
            connectedSurfaceInfo = surfaceTerminal.GetConnectedSources()[0][0]
            targetSurfacePath = UsdShade.Utils.GetConnectedSourcePath(
                connectedSurfaceInfo)
            self.assertEqual(targetSurfacePath, wetHairSurfPath)

            # Validate wet displacement terminal connection
            wetHairDispPath = hairPath.AppendChild('HairWetDisplacement')\
                                      .AppendProperty("outputs:displacement")
            dispTerminal = hairMaterial.GetDisplacementOutput()
            self.assertTrue(dispTerminal.HasConnectedSource())
            connectedDispInfo = dispTerminal.GetConnectedSources()[0][0]

            targetDispPath = UsdShade.Utils.GetConnectedSourcePath(
                connectedDispInfo)
            self.assertEqual(targetDispPath, wetHairDispPath)

            # change the root-level variantSet, which should in turn change
            # the Material's
            self.assertTrue(rootPrim\
                            .GetVariantSets()\
                            .SetSelection("materialVariant", "Dry"))
            self.assertTrue(hairMaterial)

            # Validate dry surface terminal connection
            dryHairSurfPath = hairPath.AppendChild('HairDrySurface')\
                                      .AppendProperty("outputs:surface")
            surfaceTerminal = hairMaterial.GetSurfaceOutput()
            self.assertTrue(surfaceTerminal.HasConnectedSource())
            connectedSurfaceInfo = surfaceTerminal.GetConnectedSources()[0][0]

            targetSurfacePath = UsdShade.Utils.GetConnectedSourcePath(
                connectedSurfaceInfo)
            self.assertEqual(targetSurfacePath, dryHairSurfPath)

            # Validate dry displacement terminal connection
            dryHairDispPath = hairPath.AppendChild('HairDryDisplacement')\
                                      .AppendProperty("outputs:displacement")
            dispTerminal = hairMaterial.GetDisplacementOutput()
            self.assertTrue(dispTerminal.HasConnectedSource())
            connectedDispInfo = dispTerminal.GetConnectedSources()[0][0]

            targetDispPath = UsdShade.Utils.GetConnectedSourcePath(
                connectedDispInfo)
            self.assertEqual(targetDispPath, dryHairDispPath)
    def test_Basic(self):
        usdFilePath = "Sphere.usda"

        stage = Usd.Stage.Open(usdFilePath)
        self.assertTrue(stage)

        sphere = stage.GetPrimAtPath('/Sphere/Mesh')
        mat1 = stage.GetPrimAtPath('/Sphere/Materials/initialShadingGroup')
        mat2= stage.GetPrimAtPath('/Sphere/Materials/lambert2SG')
        mat3= stage.GetPrimAtPath('/Sphere/Materials/lambert3SG')

        self.assertTrue(sphere and mat1 and mat2 and mat3)

        # Verify that the sphere mesh does not have an existing material face-set.
        geomSphere = UsdGeom.Imageable(sphere)
        materialBindSubsets = UsdShade.Material.GetMaterialBindFaceSubsets(
            geomSphere)
        self.assertEqual(len(materialBindSubsets), 0)

        faceIndices1 = Vt.IntArray((0, 1, 2, 3))
        faceIndices2 = Vt.IntArray((4, 5, 6, 7, 8, 9, 10, 11))
        faceIndices3 = Vt.IntArray((12, 13, 14, 15))

        # Create a new family of subsets with familyName="materialBind" .
        subset1 = UsdShade.Material.CreateMaterialBindFaceSubset(geomSphere, 'subset1', 
            faceIndices1)
        subset2 = UsdShade.Material.CreateMaterialBindFaceSubset(geomSphere, 'subset2', 
            faceIndices2)
        subset3 = UsdShade.Material.CreateMaterialBindFaceSubset(geomSphere, 'subset3', 
            faceIndices3)

        (valid, reason) = UsdGeom.Subset.ValidatePartition(
                            [subset1, subset2, subset3], 16)
        self.assertTrue(valid)

        UsdShade.Material(mat1).Bind(subset1.GetPrim())
        UsdShade.Material(mat2).Bind(subset2.GetPrim())
        UsdShade.Material(mat3).Bind(subset3.GetPrim())

        # Don't save the modified source stage. Export it into a 
        # new layer for baseline diffing.
        stage.Export("SphereWithMaterialBind.usda", addSourceFileComment=False)
    def _GetUsdMaterial(self, materialName):
        modelPrimPath = Sdf.Path.absoluteRootPath.AppendChild(
            'PxrUsdPreviewSurfaceExportTest')
        materialsRootPrimPath = modelPrimPath.AppendChild(
            UsdUtils.GetMaterialsScopeName())
        materialPrimPath = materialsRootPrimPath.AppendChild(materialName)
        materialPrim = self.stage.GetPrimAtPath(materialPrimPath)
        self.assertTrue(materialPrim)

        materialSchema = UsdShade.Material(materialPrim)
        self.assertTrue(materialSchema)

        return materialSchema
예제 #10
0
    def test_StdlibShaderRefs(self):
        """
        Test that we can use a shader nodedef from the MaterialX stdlib.
        """

        stage = UsdMtlx._TestFile('usd_preview_surface_gold.mtlx')
        # check stage contents
        mprim = stage.GetPrimAtPath("/MaterialX/Materials/USD_Gold")
        self.assertTrue(mprim)
        material = UsdShade.Material(mprim)
        self.assertTrue(material)
        input = material.GetInput("specularColor")
        self.assertTrue(input)
        self.assertEqual(input.GetFullName(),"inputs:specularColor")
예제 #11
0
    def read_from_file(cls,
                       file_path,
                       scene_path=None,
                       texture_path=None,
                       time=None):
        r"""Read USD material and return a Material object.
        The shader used must have a corresponding registered reader function.

        Args:
            file_path (str): Path to usd file (\*.usd, \*.usda).
            scene_path (str): Required only for reading USD files. Absolute path of UsdShade.Material prim
                within the USD file scene. Must be a valid ``Sdf.Path``.
            texture_path (str, optional): Path to textures directory. By default, the textures will be assumed to be
                under the same directory as the file specified by `file_path`.
            time (convertible to float, optional): Optional for reading USD files. Positive integer indicating the tim
                at which to retrieve parameters.

        Returns:
            (Material): Material object determined by the corresponding reader function.
        """
        if os.path.splitext(file_path)[1] in ['.usd', '.usda', '.usdc']:
            if scene_path is None or not Sdf.Path(scene_path):
                raise MaterialLoadError(
                    f'The scene_path `{scene_path}`` provided is invalid.')

            if texture_path is None:
                texture_file_path = os.path.dirname(file_path)
            elif not os.path.isabs(texture_path):
                usd_dir = os.path.dirname(file_path)
                texture_file_path = posixpath.join(usd_dir, texture_path)
            else:
                texture_file_path = texture_path

            stage = Usd.Stage.Open(file_path)
            material = UsdShade.Material(stage.GetPrimAtPath(scene_path))

            return cls.read_usd_material(material,
                                         texture_path=texture_file_path,
                                         time=time)

        elif os.path.splitext(file_path)[1] == '.obj':
            if cls._obj_reader is not None:
                return cls._obj_reader(file_path)
            else:
                raise MaterialNotSupportedError(
                    'No registered .obj material reader found.')
예제 #12
0
    def read_from_usd(self,
                      file_path,
                      scene_path,
                      texture_path=None,
                      time=None):
        r"""Read material from USD.

        Args:
            file_path (str): Path to usd file (\*.usd, \*.usda).
            scene_path (str): Absolute path of UsdShade.Material prim within the USD file scene.
                Must be a valid ``Sdf.Path``.
            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.
        """
        if time is None:
            time = Usd.TimeCode.Default()
        if texture_path is None:
            texture_file_path = os.path.dirname(file_path)
        else:
            usd_dir = os.path.dirname(file_path)
            texture_file_path = posixpath.join(usd_dir, texture_path)
        stage = Usd.Stage.Open(file_path)
        material = UsdShade.Material(stage.GetPrimAtPath(scene_path))
        assert material

        surface_shader = material.GetSurfaceOutput().GetConnectedSource()[0]
        shader = UsdShade.Shader(surface_shader)
        if shader.GetImplementationSourceAttr().Get(time=time) == 'id':
            shader_name = UsdShade.Shader(surface_shader).GetShaderId()
        else:
            raise NotImplementedError

        material_params = _get_shader_parameters(surface_shader, time)

        reader = self.shaders[shader_name]['reader']
        return reader(material_params, texture_file_path, time)
    def test_Basic(self):
        # There are a number of ways we could vary shading between wet and dry...
        # We're choosing the biggest hammer, which is to completely swap out
        # the surface shader (which is how it has been done in our pipeline)
        shadeVariations = ["Wet", "Dry"]

        # For each "base" we will have a Material, and a single Shader as the surface.
        # In reality there's likely be many more shading components/prims feeding
        # the surfaces.
        materialBases = ["Hair", "Skin", "Nails"]

        shadersPath = Sdf.Path("/ShadingDefs/Shaders")
        materialsPath = Sdf.Path("/ShadingDefs/Materials")

        def MakeSurfacePath(base, variant, prop=None):
            retval = shadersPath.AppendChild(base + variant + "Surface")
            if prop:
                retval = retval.AppendProperty(prop)
            return retval

        def MakeDisplacementPath(base, variant, prop=None):
            retval = shadersPath.AppendChild(base + variant + "Disp")
            if prop:
                retval = retval.AppendProperty(prop)
            return retval

        def MakePatternPath(base, variant, prop=None):
            retval = shadersPath.AppendChild(base + variant + "Pattern")
            if prop:
                retval = retval.AppendProperty(prop)
            return retval

        def MakeMaterialPath(base, prop=None):
            retval = materialsPath.AppendChild(base + "Material")
            if prop:
                retval = retval.AppendProperty(prop)
            return retval

        #def CreateTerminal(material, name, targetPath):
        #terminalRel = material.GetPrim().CreateRelationship("terminal:%s" % name)
        #terminalRel.SetTargets([targetPath,]);
        #return terminalRel

        def SetupShading(stage):
            # First create the shading prims
            UsdGeom.Scope.Define(stage, shadersPath)
            UsdGeom.Scope.Define(stage, materialsPath)
            # .. and as we create each surface, bind the associated material's variant to it
            allMaterials = []
            for material in materialBases:
                materialPrim = UsdShade.Material.Define(
                    stage, MakeMaterialPath(material))
                allMaterials.append(materialPrim.GetPrim())
                for variant in shadeVariations:
                    surface = UsdShade.Shader.Define(
                        stage, MakeSurfacePath(material, variant))
                    colorOut = surface.CreateOutput("out",
                                                    Sdf.ValueTypeNames.Color3f)

                    disp = UsdShade.Shader.Define(
                        stage, MakeDisplacementPath(material, variant))
                    dispOut = disp.CreateOutput('out',
                                                Sdf.ValueTypeNames.Vector3f)

                    pattern = UsdShade.Shader.Define(
                        stage, MakePatternPath(material, variant))
                    patternOut = pattern.CreateOutput(
                        "out", Sdf.ValueTypeNames.FloatArray)

                    with materialPrim.GetEditContextForVariant(variant):
                        surfaceOutput = materialPrim.CreateOutput(
                            "surface", colorOut.GetTypeName())
                        UsdShade.ConnectableAPI.ConnectToSource(
                            surfaceOutput,
                            UsdShade.ConnectableAPI(colorOut.GetPrim()),
                            colorOut.GetBaseName(),
                            UsdShade.AttributeType.Output)

                        displacementOutput = materialPrim.CreateOutput(
                            "displacement", dispOut.GetTypeName())
                        UsdShade.ConnectableAPI.ConnectToSource(
                            displacementOutput, dispOut)

                        patternOutput = materialPrim.CreateOutput(
                            "pattern", patternOut.GetTypeName())
                        UsdShade.ConnectableAPI.ConnectToSource(
                            patternOutput, patternOut)

                        # XXX: If we replace these terminals with UsdShadeOutput's, then
                        ## we can't have these point to prim paths.
                        #surfacePath = MakeSurfacePath(material, variant, 'out')
                        #CreateTerminal(materialPrim, "surface", surfacePath)

                        #dispPath = MakeDisplacementPath(material, variant, 'out')
                        #CreateTerminal(materialPrim, "displacement", dispPath)

                        #CreateTerminal(materialPrim, 'pattern',
                        #MakePatternPath(material, variant, 'out'))

            return allMaterials

        def ValidateMaterial(stage):
            hairPrim = stage.GetPrimAtPath(
                '/ModelShading/Materials/HairMaterial')
            hairMaterial = UsdShade.Material(hairPrim)
            self.assertTrue(hairMaterial)
            wetHairSurfPath = Sdf.Path(
                '/ModelShading/Shaders/HairWetSurface.out')
            wetHairDispPath = Sdf.Path('/ModelShading/Shaders/HairWetDisp.out')
            wetHairPatternPath = Sdf.Path(
                '/ModelShading/Shaders/HairWetPattern.out')

            connectedSurface = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('surface'))
            connectedSurfacePath = connectedSurface[0].GetPath(
            ).AppendProperty(connectedSurface[1])
            self.assertEqual(connectedSurfacePath, wetHairSurfPath)

            connectedDisplacement = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('displacement'))
            connectedDisplacementPath = connectedDisplacement[0].GetPath(
            ).AppendProperty(connectedDisplacement[1])
            self.assertEqual(connectedDisplacementPath, wetHairDispPath)

            connectedPattern = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('pattern'))
            connectedPatternPath = connectedPattern[0].GetPath(
            ).AppendProperty(connectedPattern[1])
            self.assertEqual(connectedPatternPath, wetHairPatternPath)

            # change the root-level variantSet, which should in turn change the Material's
            self.assertTrue(rootPrim.GetVariantSets().SetSelection(
                "materialVariant", "Dry"))
            self.assertTrue(hairMaterial)
            dryHairSurfPath = Sdf.Path(
                '/ModelShading/Shaders/HairDrySurface.out')
            dryHairDispPath = Sdf.Path('/ModelShading/Shaders/HairDryDisp.out')
            dryHairPatternPath = Sdf.Path(
                '/ModelShading/Shaders/HairDryPattern.out')

            connectedSurface = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('surface'))
            connectedSurfacePath = connectedSurface[0].GetPath(
            ).AppendProperty(connectedSurface[1])
            self.assertEqual(connectedSurfacePath, dryHairSurfPath)

            connectedDisplacement = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('displacement'))
            connectedDisplacementPath = connectedDisplacement[0].GetPath(
            ).AppendProperty(connectedDisplacement[1])
            self.assertEqual(connectedDisplacementPath, dryHairDispPath)

            connectedPattern = UsdShade.ConnectableAPI.GetConnectedSource(
                hairMaterial.GetOutput('pattern'))
            connectedPatternPath = connectedPattern[0].GetPath(
            ).AppendProperty(connectedPattern[1])
            self.assertEqual(connectedPatternPath, dryHairPatternPath)

        fileName = "char_shading.usda"
        stage = Usd.Stage.CreateNew(fileName)

        # Create this prim first, since it's the "entrypoint" to the layer, and
        # we want it to appear at the top
        rootPrim = stage.DefinePrim("/ModelShading")

        # Next, create a tree that will "sit on top of ShadingDefs" to switch the
        # materials in concert
        allMaterials = SetupShading(stage)
        bindingVariantRoot = stage.OverridePrim("/MaterialBindingVariants")
        UsdShade.Material.CreateMasterMaterialVariant(bindingVariantRoot,
                                                      allMaterials)

        # Finally, this is how we stitch them together into an interface.
        # This is the root prim that a client would target to pull in shading
        refs = rootPrim.GetReferences()
        # XXX We need a better way of specifying self-references
        refs.AppendReference("./" + fileName, "/MaterialBindingVariants")
        refs.AppendReference("./" + fileName, "/ShadingDefs")

        stage.GetRootLayer().Save()

        # Now let's do some validation that it performs as expected
        ValidateMaterial(stage)

        # Now let's make a variation of the above in which we do the master variant
        # on a composed stage in which rootPrim is already referencing the ShadingDefs,
        # and operating on the composed Material prims
        fileName = "char_shading_compact.usda"
        stage = Usd.Stage.CreateNew(fileName)

        # Create this prim first, since it's the "entrypoint" to the layer, and
        # we want it to appear at the top
        rootPrim = stage.DefinePrim("/ModelShading")

        SetupShading(stage)
        # Reference the shading directly
        refs = rootPrim.GetReferences()
        refs.AppendReference("./" + fileName, "/ShadingDefs")

        # Now pick up the newly composed material prims
        allMaterials = [
            stage.GetPrimAtPath("/ModelShading/Materials/HairMaterial"),
            stage.GetPrimAtPath("/ModelShading/Materials/SkinMaterial"),
            stage.GetPrimAtPath("/ModelShading/Materials/NailsMaterial")
        ]

        UsdShade.Material.CreateMasterMaterialVariant(rootPrim, allMaterials)

        stage.GetRootLayer().Save()

        # Now let's do some validation that it performs as expected
        ValidateMaterial(stage)

        # TODO: move this into it's own test
        hairPrim = stage.GetPrimAtPath('/ModelShading/Materials/HairMaterial')
        hairMaterial = UsdShade.Material(hairPrim)
        interfaceAttribute = hairMaterial.CreateInterfaceAttribute(
            "myParam", Sdf.ValueTypeNames.Float)
        interfaceAttribute.SetDocumentation("this is my float")
        interfaceAttribute.SetDisplayGroup("numbers")

        # Make sure the IA is namespaced, but also that we can retrieve it with or
        # without the namespace
        plain = hairPrim.GetAttribute("interface:myParam")
        self.assertTrue(plain and (plain.GetTypeName() == "float"))

        # plain was a UsdAttribue, but these are UsdShadeInterfaceAttributes
        byName = hairMaterial.GetInterfaceAttribute("myParam")
        self.assertTrue(byName
                        and (byName.GetDocumentation() == "this is my float"))

        fullName = hairMaterial.GetInterfaceAttribute("interface:myParam")
        self.assertTrue(fullName and (fullName.GetDisplayGroup() == "numbers"))
예제 #14
0
# Allow module import from the parent path.
import os, sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
import framework
from pxr import Usd, UsdGeom, UsdShade

stage = framework.createWorkStage("clean_cube.usda")
framework.appendLayer(stage, "more_materials.usda")

cubePrim = stage.GetPrimAtPath("/Cube")
blueMaterial = UsdShade.Material(stage.GetPrimAtPath("/Looks/Blue"))
UsdShade.MaterialBindingAPI(cubePrim).Bind(blueMaterial)

framework.viewUsdStage(stage)
framework.printWorkStage(stage)
예제 #15
0
    def add_mesh_batch(self,
                       iteration=0,
                       category='',
                       vertices_list=None,
                       faces_list=None,
                       uvs_list=None,
                       face_uvs_idx_list=None,
                       face_normals_list=None,
                       materials_list=None):
        """
        Add meshes to visualizer output.

        Args:
            iteration (int): Positive integer identifying the iteration the supplied meshes belong to.
            category (str, optional): Batch name.
            vertices_list (list of tensors, optional): Vertices for N meshes of shape (num_vertices, 3).
            faces_list (list of tensors, optional): Faces for N meshes of shape (num_faces, face_size).
            uvs_list (list of tensors, optional): UV coordinates for N meshes of shape (num_uvs, 2).
            face_uvs_idx_list (list of tensors, optional): Index of UV coordinates for N meshes of shape (num_faces, face_size).
            face_normals_list (list of tensors, optional): Face normals for N meshes of shape (num_faces, face_size, 3).
            materials_list (list, optional): List of materials for N meshes. For each mesh, if a list of io.Materials is
                supplied, each material is applied to the mesh as a ShadingVariant. A name for each material can be defined
                by supplying a dictionary in the form of {'material_name': material}.
        """
        validated = self._validate_parameters(
            vertices_list=vertices_list,
            faces_list=faces_list,
            uvs_list=uvs_list,
            face_uvs_idx_list=face_uvs_idx_list,
            face_normals_list=face_normals_list,
            materials_list=materials_list)

        meshes_path = posixpath.join(self.logdir, category)
        textures_path = posixpath.join(meshes_path, 'textures')
        os.makedirs(meshes_path, exist_ok=True)
        os.makedirs(textures_path, exist_ok=True)

        for i, sample in enumerate(zip(*validated)):
            vertices, faces, uvs, face_uvs_idx, face_normals, materials = sample
            # Establish default USD file paths for sample
            mesh_name = f'mesh_{i}'
            ind_out_path = posixpath.join(meshes_path, f'{mesh_name}.usd')

            if not os.path.exists(ind_out_path):
                # If sample does not exist, create it.
                stage = io.usd.create_stage(ind_out_path)
                mesh_prim = stage.DefinePrim(f'/{mesh_name}', 'Mesh')
                stage.SetDefaultPrim(stage.GetPrimAtPath(f'/{mesh_name}'))
                if materials_list is not None:
                    for material_name, _ in materials_list[i].items():
                        self._add_shading_variant(mesh_prim, material_name)
            else:
                stage = Usd.Stage.Open(ind_out_path)
                mesh_prim = stage.GetPrimAtPath(f'/{mesh_name}')

            # Adjust end timecode to match current iteration
            stage.SetEndTimeCode(iteration)

            io.usd.add_mesh(stage,
                            f'/{mesh_name}',
                            vertices,
                            faces,
                            uvs,
                            face_uvs_idx,
                            face_normals,
                            time=iteration)
            if materials is not None:
                if isinstance(materials, io.materials.Material):
                    materials = {'0': materials}
                if isinstance(materials, list):
                    materials = {str(i): v for i, v in enumerate(materials)}
                vset = mesh_prim.GetVariantSets().GetVariantSet(
                    'shadingVariant')
                for material_name, material in materials.items():
                    vset.SetVariantSelection(material_name)
                    material.usd_root_path = meshes_path
                    with vset.GetVariantEditContext():
                        material_prim = material.write_to_usd(
                            ind_out_path,
                            f'/{mesh_name}/{material_name}',
                            time=iteration,
                            texture_dir='textures',
                            texture_file_prefix=
                            f'{mesh_name}_{material_name}_{iteration}_')
                        binding_api = UsdShade.MaterialBindingAPI(mesh_prim)
                        binding_api.Bind(UsdShade.Material(material_prim))
            stage.Save()
예제 #16
0
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
import framework
from pxr import Usd, UsdGeom, UsdShade, Vt

stage = framework.createWorkStage("fort.usda")
framework.appendLayer(stage, "more_materials.usda")

doorPrim = stage.GetPrimAtPath("/Meshes/Door/Cube_002")
leftTowerPrim = stage.GetPrimAtPath("/Meshes/LeftTower/Cylinder")
leftCanopyPrim = stage.GetPrimAtPath("/Meshes/LeftCanopy/Cone")
mainPrim = stage.GetPrimAtPath("/Meshes/Main/Cube")
outcroppingPrim = stage.GetPrimAtPath("/Meshes/Outcropping/Cube_001")
rightTowerPrim = stage.GetPrimAtPath("/Meshes/RightTower/Cylinder_001")
rightCanopyPrim = stage.GetPrimAtPath("/Meshes/RightCanopy/Cone_001")

blueMaterial = UsdShade.Material(stage.GetPrimAtPath("/Looks/Blue"))
redMaterial = UsdShade.Material(stage.GetPrimAtPath("/Looks/Red"))
greenMaterial = UsdShade.Material(stage.GetPrimAtPath("/Looks/Green"))
yellowMaterial = UsdShade.Material(stage.GetPrimAtPath("/Looks/Yellow"))

rootPrim = stage.GetPrimAtPath("/Meshes")
collections = [
    Usd.CollectionAPI.ApplyCollection(rootPrim, "left"),
    Usd.CollectionAPI.ApplyCollection(rootPrim, "right"),
    Usd.CollectionAPI.ApplyCollection(rootPrim, "centre"),
    Usd.CollectionAPI.ApplyCollection(rootPrim, "misc")
]

collections[0].IncludePath("/Meshes/LeftTower/Cylinder")
collections[0].IncludePath("/Meshes/LeftCanopy/Cone")
collections[1].IncludePath("/Meshes/RightTower/Cylinder_001")
 def _GetMaterial(self, stage, path):
     material = UsdShade.Material(stage.GetPrimAtPath(path))
     self.assertTrue(material)
     return material
예제 #18
0
    def test_Basic(self):
        usdFilePath = "Sphere.usda"

        stage = Usd.Stage.Open(usdFilePath)
        self.assertTrue(stage)

        sphere = stage.GetPrimAtPath('/Sphere/Mesh')
        mat1 = stage.GetPrimAtPath('/Sphere/Materials/initialShadingGroup')
        mat2 = stage.GetPrimAtPath('/Sphere/Materials/lambert2SG')
        mat3 = stage.GetPrimAtPath('/Sphere/Materials/lambert3SG')

        self.assertTrue(sphere and mat1 and mat2 and mat3)

        # Verify that the sphere mesh does not have an existing material face-set.
        geomSphere = UsdGeom.Imageable(sphere)
        materialBindSubsets = UsdShade.Material.GetMaterialBindSubsets(
            geomSphere)
        self.assertEqual(len(materialBindSubsets), 0)

        faceIndices1 = Vt.IntArray((0, 1, 2, 3))
        faceIndices2 = Vt.IntArray((4, 5, 6, 7, 8, 9, 10, 11))
        faceIndices3 = Vt.IntArray((12, 13, 14, 15))

        # Create a new family of subsets with familyName="materialBind" .
        subset1 = UsdShade.Material.CreateMaterialBindSubset(
            geomSphere, 'subset1', faceIndices1, UsdGeom.Tokens.face)
        # Default elementType is 'face'
        subset2 = UsdShade.Material.CreateMaterialBindSubset(
            geomSphere, 'subset2', faceIndices2)
        self.assertEqual(subset2.GetElementTypeAttr().Get(),
                         UsdGeom.Tokens.face)

        (valid,
         reason) = UsdGeom.Subset.ValidateFamily(geomSphere,
                                                 UsdGeom.Tokens.face,
                                                 UsdShade.Tokens.materialBind)
        self.assertTrue(valid)

        (valid, reason) = UsdGeom.Subset.ValidateSubsets(
            [subset1, subset2],
            elementCount=16,
            familyType=UsdGeom.Tokens.nonOverlapping)
        self.assertTrue(valid)

        # Not quite a partition yet.
        (valid, reason) = UsdGeom.Subset.ValidateSubsets(
            [subset1, subset2],
            elementCount=16,
            familyType=UsdGeom.Tokens.partition)
        self.assertFalse(valid)

        # Add a subset that makes the family a partition.
        subset3 = UsdShade.Material.CreateMaterialBindSubset(
            geomSphere, 'subset3', faceIndices3)
        (valid, reason) = UsdGeom.Subset.ValidateSubsets(
            [subset1, subset2, subset3],
            elementCount=16,
            familyType=UsdGeom.Tokens.partition)
        self.assertTrue(valid)

        self.assertEqual(
            UsdShade.Material.GetMaterialBindSubsetsFamilyType(geomSphere),
            UsdGeom.Tokens.nonOverlapping)

        UsdShade.Material.SetMaterialBindSubsetsFamilyType(
            geomSphere, UsdGeom.Tokens.partition)

        (valid,
         reason) = UsdGeom.Subset.ValidateFamily(geomSphere,
                                                 UsdGeom.Tokens.face,
                                                 UsdShade.Tokens.materialBind)
        self.assertTrue(valid)

        UsdShade.Material(mat1).Bind(subset1.GetPrim())
        UsdShade.Material(mat2).Bind(subset2.GetPrim())
        UsdShade.Material(mat3).Bind(subset3.GetPrim())

        # Don't save the modified source stage. Export it into a
        # new layer for baseline diffing.
        stage.Export("SphereWithMaterialBind.usda", addSourceFileComment=False)
예제 #19
0
    def test_Basic(self):

        shadingDefs = Sdf.Path("/ShadingDefs")

        # There are a number of ways we could vary shading between wet and dry.
        # We're choosing the biggest hammer, which is to completely swap out
        # the surface shader (which is how it has been done in Pixar's pipeline)
        shadeVariations = ["Wet", "Dry"]

        # For each "base" we will have a Material, and a single Shader as the
        # surface.  In reality there's likely be many more shading
        # components/prims feeding the surfaces.
        materialBases = ["Hair", "Skin", "Nails"]

        # We often create Shaders "inline" under the Material that uses them,
        # but here we put all Shaders in a common, external prim that will
        # be referenced into each Material; since we will be creating inline
        # VariantSets for the materials, this structure ensures the Shader
        # definitions are weaker than any of the Variant opinions.
        shadersPath = shadingDefs.AppendChild("Shaders")
        materialsPath = shadingDefs.AppendChild("Materials")

        # If `referencedPropName` is provided, construct a path to that
        # prop in the *referenced location of the implied shader.  Otherwise,
        # return a path to the _definition_ for the shader.
        def MakeShadingPath(base, variant, category, referencedPropName=None):
            if referencedPropName:
                return materialsPath.AppendChild(base + "Material")\
                                    .AppendChild(base + variant + category)\
                                    .AppendProperty(referencedPropName)
            else:
                return shadersPath.AppendChild(base + variant + category)

        def MakeSurfacePath(base, variant, referencedPropName=None):
            return MakeShadingPath(base, variant, "Surface",
                                   referencedPropName)

        def MakeDisplacementPath(base, variant, referencedPropName=None):
            return MakeShadingPath(base, variant, "Displacement",
                                   referencedPropName)

        def MakeMaterialPath(base, prop=None):
            retval = materialsPath.AppendChild(base + "Material")
            if prop:
                retval = retval.AppendProperty(prop)
            return retval

        def SetupShading(stage):
            # First create the shading prims
            UsdGeom.Scope.Define(stage, shadersPath)
            UsdGeom.Scope.Define(stage, materialsPath)

            allMaterials = []
            for material in materialBases:
                # Create and remember each Material, and reference in the
                # complete set of shaders onto each Material prim
                materialPrim = UsdShade.Material.Define(
                    stage, MakeMaterialPath(material))
                materialPrim.GetPrim().\
                    GetReferences().AddInternalReference(shadersPath)
                allMaterials.append(materialPrim.GetPrim())

                for variant in shadeVariations:
                    # .. and as we create each surface, bind the associated
                    # material's variant to it
                    surface = UsdShade.Shader.Define(
                        stage, MakeSurfacePath(material, variant))
                    surfaceOut = surface.CreateOutput("surface",
                                                      Sdf.ValueTypeNames.Token)

                    disp = UsdShade.Shader.Define(
                        stage, MakeDisplacementPath(material, variant))
                    dispOut = disp.CreateOutput("displacement",
                                                Sdf.ValueTypeNames.Token)

                    with materialPrim.GetEditContextForVariant(variant):
                        surfaceOutput = materialPrim.CreateSurfaceOutput()
                        surfaceOutput.ConnectToSource(
                            MakeSurfacePath(material, variant,
                                            surfaceOut.GetFullName()))

                        displacementOutput = materialPrim.\
                                             CreateDisplacementOutput()
                        displacementOutput.ConnectToSource(
                            MakeDisplacementPath(material, variant,
                                                 dispOut.GetFullName()))

            # Change root prim to an over so it is not traversed by the stage
            stage.GetPrimAtPath(shadingDefs).SetSpecifier(Sdf.SpecifierOver)

            return allMaterials

        def ValidateMaterial(stage):
            hairPath = Sdf.Path('/ModelShading/Materials/HairMaterial')
            hairPrim = stage.GetPrimAtPath(hairPath)
            hairMaterial = UsdShade.Material(hairPrim)
            self.assertTrue(hairMaterial)

            # Validate wet surface terminal connection
            wetHairSurfPath = hairPath.AppendChild('HairWetSurface')\
                                      .AppendProperty("outputs:surface")
            surfaceTerminal = hairMaterial.GetSurfaceOutput()
            self.assertTrue(surfaceTerminal.HasConnectedSource())
            connectedSurfaceInfo = surfaceTerminal.GetConnectedSources()[0][0]
            targetSurfacePath = UsdShade.Utils.GetConnectedSourcePath(
                connectedSurfaceInfo)
            self.assertEqual(targetSurfacePath, wetHairSurfPath)

            # Validate wet displacement terminal connection
            wetHairDispPath = hairPath.AppendChild('HairWetDisplacement')\
                                      .AppendProperty("outputs:displacement")
            dispTerminal = hairMaterial.GetDisplacementOutput()
            self.assertTrue(dispTerminal.HasConnectedSource())
            connectedDispInfo = dispTerminal.GetConnectedSources()[0][0]

            targetDispPath = UsdShade.Utils.GetConnectedSourcePath(
                connectedDispInfo)
            self.assertEqual(targetDispPath, wetHairDispPath)

            # change the root-level variantSet, which should in turn change
            # the Material's
            self.assertTrue(rootPrim\
                            .GetVariantSets()\
                            .SetSelection("materialVariant", "Dry"))
            self.assertTrue(hairMaterial)

            # Validate dry surface terminal connection
            dryHairSurfPath = hairPath.AppendChild('HairDrySurface')\
                                      .AppendProperty("outputs:surface")
            surfaceTerminal = hairMaterial.GetSurfaceOutput()
            self.assertTrue(surfaceTerminal.HasConnectedSource())
            connectedSurfaceInfo = surfaceTerminal.GetConnectedSources()[0][0]

            targetSurfacePath = UsdShade.Utils.GetConnectedSourcePath(
                connectedSurfaceInfo)
            self.assertEqual(targetSurfacePath, dryHairSurfPath)

            # Validate dry displacement terminal connection
            dryHairDispPath = hairPath.AppendChild('HairDryDisplacement')\
                                      .AppendProperty("outputs:displacement")
            dispTerminal = hairMaterial.GetDisplacementOutput()
            self.assertTrue(dispTerminal.HasConnectedSource())
            connectedDispInfo = dispTerminal.GetConnectedSources()[0][0]

            targetDispPath = UsdShade.Utils.GetConnectedSourcePath(
                connectedDispInfo)
            self.assertEqual(targetDispPath, dryHairDispPath)

        def SetupStage(stage):
            UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.y)
            UsdGeom.SetStageMetersPerUnit(stage,
                                          UsdGeom.LinearUnits.centimeters)

            # Create this prim first, since it's the "entrypoint" to the
            # layer, and we want it to appear at the top
            rootPrim = stage.DefinePrim("/ModelShading")
            stage.SetDefaultPrim(rootPrim)
            return rootPrim

        stage = Usd.Stage.CreateNew("char_shading.usda")
        rootPrim = SetupStage(stage)

        # Next, create a tree that will "sit on top of ShadingDefs" to switch
        # the materials in concert
        allMaterials = SetupShading(stage)
        bindingVariantRoot = stage.OverridePrim("/MaterialBindingVariants")
        UsdShade.Material.CreateMasterMaterialVariant(bindingVariantRoot,
                                                      allMaterials)

        # Finally, this is how we stitch them together into an interface.
        # This is the root prim that a client would target to pull in shading
        refs = rootPrim.GetReferences()
        refs.AddInternalReference("/MaterialBindingVariants")
        refs.AddInternalReference(shadingDefs)

        stage.Save()

        # Now let's do some validation that it performs as expected
        ValidateMaterial(stage)

        # Now let's make a variation of the above in which we do the master
        # variant on a composed stage in which rootPrim is already
        # referencing the ShadingDefs, and operating on the composed Material
        # prims
        stage = Usd.Stage.CreateNew("char_shading_compact.usda")
        rootPrim = SetupStage(stage)

        # Ignore the return value, since we do not process the materials in
        # their authored namespace, in this version
        SetupShading(stage)
        # Reference the shading directly
        refs = rootPrim.GetReferences()
        refs.AddInternalReference(shadingDefs)

        # Now pick up the newly composed material prims
        allMaterials = [
            stage.GetPrimAtPath("/ModelShading/Materials/HairMaterial"),
            stage.GetPrimAtPath("/ModelShading/Materials/SkinMaterial"),
            stage.GetPrimAtPath("/ModelShading/Materials/NailsMaterial")
        ]

        UsdShade.Material.CreateMasterMaterialVariant(rootPrim, allMaterials)

        stage.Save()

        # Now let's do some validation that it performs as expected
        ValidateMaterial(stage)

        # TODO: move this into it's own test
        hairPrim = stage.GetPrimAtPath('/ModelShading/Materials/HairMaterial')
        hairMaterial = UsdShade.Material(hairPrim)
        interfaceInput = hairMaterial.CreateInput("myParam",
                                                  Sdf.ValueTypeNames.Float)
        interfaceInput.SetDocumentation("this is my float")
        interfaceInput.SetDisplayGroup("numbers")

        byName = hairMaterial.GetInput("myParam")
        self.assertTrue(byName
                        and (byName.GetDocumentation() == "this is my float")
                        and (byName.GetDisplayGroup() == "numbers"))

        plain = hairPrim.GetAttribute(byName.GetFullName())
        self.assertTrue(plain and (plain.GetTypeName() == "float"))