Getting faces within a set

Hi,

So the problem I have is that I have a piece of geometry that has 3 materials assigned to a range of faces in Maya. I’m using python btw. What I essentially want to do is query which range of faces are connected to each material and then assign a new material to that range of faces. I’ve tried running through the listConnections command in python when it comes to determining what is connected to the shadingEngine and it only returns the mesh that the shader is attached to. In the Hypershade, the shadingEngine node is connected to the mesh via object.instObjGroups[0].objectGroups[0] -> dagSetMembers[0] & object.instObjGroups[0].objectGroups[2] -> dagSetMembers[2] respectively, and if I had to wager a guess I’d say the range of faces are contained in their somewhere but how do I access that information? Anyone have any insights?

you can use the “sets” command to query the members of a shading group.
you will then need to filter out of the membership list the polygons that do not belong to the mesh you want to operate on.


mat2face = {}
sgs = cmds.listConnections(myGeo, type='shadingEngine')
for sg in sgs:
    faces = []
    members = cmds.sets(sg, q=True)
    for item in members:
        if myGeo in item:
             faces.append(item)
    mat2face[sg] = faces

returns a dictionary where each material on a model is a key, and the faces mapped to that material is the value.

p.s. this code is written off the top of my head, so it may not work as-is…


results = cmds.sets('initialShadingGroup', q=True) or []
add_suffix = lambda p:  p + ".f[li]" if not '.f' in p else p[/li]results = [ add_suffix(r) for r in results] or []
print  cmds.filterExpand(*results, sm=34) or []

Ought to do it. Replace the string with the name of your shadingGroup

I think @RGKovachs’ answer is the same thing, except his may choke if the material is assigned per object and not per face.

sometimes maya will give you the transform name with the poly component and other times it will give you the shape node.

‘pCube1.f[1]’ versus ‘pCubeShape1.f[1]’

its important to always make sure your queries come back in the same format, otherwise you can’t use string methods to determine if a component belongs to mesh without jumping through more hoops.

using “if mesh in item:” should work if mesh and item are the same value… ?

Theodox, what does your example return? The members of “initialShadingGroup” sorted by mesh?

Where do you tell it to filter out faces that belong to a specific mesh?

My snippet, given a shading group, returns all of the faces in the scene assigned to that shading group. You could easily make it into a def by turning the string into a variable:


def get_sg_faces(sg):
    results = cmds.sets(sg, q=True) or [] 
    add_suffix = lambda p:  p + ".f[li]" if not '.f' in p else p[/li]    results = [ add_suffix(r) for r in results]
    return  cmds.filterExpand(*results, sm=34) or []

where sg is the shading group name. It’s not sorted by mesh, it’s just a flat list of all the face components used by the sg – filtering is just checking for mesh in the returned components the way you do.

@RG … I wrote mine while you were writing yours, so I was responding to OP’s question about tracking the components down, not your answer to his larger problem.

Now you mention it, there would be a perf gain in filtering the mesh names before the filterexpand for large sets:


def get_sg_faces(sg, meshname):
    results = cmds.sets(sg, q=True) or [] 
    add_suffix = lambda p:  p + ".f[li]" if not '.f' in p else p[/li]    results = [ add_suffix(r) for r in results if meshname in r ]
    return  cmds.filterExpand(*results, sm=34) or []