Replicator assign existing material list to randomizer

Is there a possibility to assign existing materials in the Replicator randomizer and edit them in the same step/for every new scene? I did not see an example and my approach does not work unfortunately. I also want to give all props instances the same material for one scene and then in the next scene give them a new material from the list.

In my approach I created a materials.usd and imported them (this works), put the prim paths in a list and tried to give the list to the rep.randomizer.materials() function. I did not try to edit the materials since the assigning did not work for now, but it would be awesome to do this in the future version of my script. I will provide the code below:

base_path ="omniverse://127.0.0.1/BinPicking/BinPicking/"
Materials = base_path + "materials.usd"
mat_prim_path = "/World/materials"
add_reference_to_stage(usd_path=Materials, prim_path=mat_prim_path)
#Set materials
mat = get_prim_at_path(mat_prim_path)
materials_list = []
for n in Usd.PrimRange(mat):
        if n.GetTypeName() == 'Material':
            materials_list.append(n.GetPrimPath())

instances = rep.randomizer.instantiate(rep.utils.get_usd_files(PROPS, recursive=True), size=size, mode='scene_instance')
        with instances:
            rep.modify.semantics([('class', 'ring')])
            rep.modify.pose(
                position=rep.distribution.uniform((-0.5, -0.5, 0.2), (0.5, 0.5, 0.3)),
                rotation=rep.distribution.uniform((0,-180, 0), (0, 180, 0)),
                scale = 1
            )

            rep.randomizer.materials(materials=materials_list) 
        return instances.node

A workaround for this would be to create a primvar by adding an attribute to your prim and a Material that accesses those primvars.

import omni.replicator.core as rep

with rep.new_layer():
    sphere = rep.get.prims(path_pattern="/World/Sphere")
    
    def sphere_color():
        with sphere:
            rep.modify.attribute("primvars:color_override", rep.distribution.uniform((0, 0, 0), (1,1,1)))
        return sphere.node

    rep.randomizer.register(sphere_color)

    # Setup randomization
    with rep.trigger.on_frame(num_frames=10):
        rep.randomizer.sphere_color()

Sample of what the Material Graph would look like:

Video running preview with Replicator:

Here is a copy of the file if you want to see it working with the code snippet: color_override.usd (51.1 KB)

Thank you @kit-nvidia-Jen, I will test in on Monday. But this seems to only change the colour of a material and not the whole material itself or did I not understand right? I want to import some materials from my nucleus server, save them in a list and randomize the chosen material for all instances in the scene I want to drop. I want to create a bin-picking scenario with different materials.

Then you would want to create a list/array of material’s paths and pass that in as the argument. In your case it would be the path of the materials on your nucleus server. Example:


import omni.replicator.core as rep

with rep.new_layer():
    mats = ['/World/Looks/OmniPBR', '/World/Looks/OmniPBR_01']
    spheres = rep.create.sphere(
        scale=0.2,
        position=rep.distribution.uniform((-100,-100,-100), (100,100,100)),
        count=100)


    def get_spheres():
        with spheres:
            rep.randomizer.materials(mats)
        return spheres.node

    rep.randomizer.register(get_spheres)

    # Setup randomization
    with rep.trigger.on_frame(num_frames=1):
        rep.randomizer.get_spheres()

Okay I thought that was what I have done with my for loop. It showed me the correct prim paths, but the functionality was not there. Is it a problem that they are all in the same .usd file when imported? Should I import them seperately? Or because I did it outside of the new layer?

base_path ="omniverse://127.0.0.1/BinPicking/BinPicking/"
Materials = base_path + "materials.usd"
mat_prim_path = "/World/materials"
add_reference_to_stage(usd_path=Materials, prim_path=mat_prim_path)
#Set materials
mat = get_prim_at_path(mat_prim_path)
materials_list = []
for n in Usd.PrimRange(mat):
        if n.GetTypeName() == 'Material':
            materials_list.append(n.GetPrimPath())

It should be fine if it’s in the same .usd file. When I used layers the functionality does not seem to work but working with just a single layer worked fine. Could you try without making any layers?

Another thing to consider is if you have the path name to the .mdl file that should work as well. I.e. omniverse://localhost/NVIDIA/Materials/Base/Carpet/Carpet_Berber_Gray.mdl

@kit-nvidia-Jen Okay I tried it out now: The problem was not the creating in a layer, this seems to work just fine for me, it was the for-loop. Without the for-loop and just adding the prim path to each material it works fine. I will post the output with the for-loop and the list without it, so you can have a look at it. Now I got another question: Right now the materials in 1 scene are mixed, but is there a possibility to give every instance the same material in 1 scene and in the next it is randomized again that they have a new material but all instances the same?

Thank you very much!

List with for-loop:

materials_list=[Sdf.Path('/World/materials/Looks/Steel_Cast'), Sdf.Path('/World/materials/Looks/Aluminum_Cast'), Sdf.Path('/World/materials/Looks/Cast_Metal_Silver_Vein'), Sdf.Path('/World/materials/Looks/RustedMetal'), Sdf.Path('/World/materials/Looks/Steel_Blued'), Sdf.Path('/World/materials/Looks/Plastic_ABS')]

List without for-loop:

materials_list = ["/World/materials/Looks/Steel_Cast",'/World/materials/Looks/Aluminum_Cast','/World/materials/Looks/Cast_Metal_Silver_Vein','/World/materials/Looks/RustedMetal','/World/materials/Looks/Steel_Blued','/World/materials/Looks/Plastic_ABS']

I see, so for the for loop you might want to cast the path to a string before appending.

for n in Usd.PrimRange(mat):
        if n.GetTypeName() == 'Material':
            materials_list.append(str(n.GetPrimPath()))

When you instantiate your prims you can set the material.

import omni.replicator.core as rep

rep.create.cube(material=material_path)

Thank you very much! Such a stupid mistake from me, I am sorry.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.