简体   繁体   中英

Assign shaders from one mesh to another in Maya via Python

I am looking for a way how to transfer shaders from one character to another character if they are totally similar. So I am looking for the way how to query shader from one face of the mesh to another completely similar one. I am already stuck on the moment how to query shader.

Anybody can give some tips?

Thanks

Select source model and then select any number of target models (but with the same topology) and execute the following MEL code:

global proc polyTransferShadingGroups(string $objects[]) {

    string $src = $objects[0];
    string $targ;
    int $targcount = size($objects);
    int $i;

    for($i = 1; $i < $targcount; ++$i) {
        string $targ = $objects[$i];
        string $shGroups[] = listSets -ets -type 1 -o $src;
        string $sg;

        for($sg in $shGroups) {
            string $sgMembers[] = sets -q $sg;
            string $f;

            for($f in $sgMembers) {
                string $obj = match(".*\.", $f);
                $obj = substitute("\.", $obj, "");

                if($obj == $src) {
                    string $index = match("\..*", $f);
                    sets -e -fe $sg ($targ + $index);
                }
            }
        }
    }
}
polyTransferShadingGroups(ls -sl);
import maya.cmds as cmds
import re

def inRange(selection, fList):
    try:
        # extract ids 1234:5464 or just a number
        ranges = [ re.findall('(\d+:?\d+)', x)[0] for x in fList]
        # extract the id of our current face
        selectionIndex = re.findall('(\d+:?\d+)', selection)[-1]
    except:
        #if extraction above fail, it is not the good shader
        return False
    if selectionIndex in ranges:
        # if it is not a range 12354:46548
        # we check if our face is in the list
        return True
    else:
        # if it is a range, 13215:484984, let's check if our face id is between : 13215 >= ourFace <= 484984
        if [True for i in ranges if int(selectionIndex) >= int(i.split(':')[0]) and int(selectionIndex) <= int(i.split(':')[-1])]:
            return True
    # If everything above is not working, our face is not in the shader set
    return False

def shadeSimilar(target=list):   
    # split selected face to have the transofrm and the face id
    sel = cmds.ls(sl=True)[0].split('.')
    # lets query the shape to list every shaders connected
    shape = cmds.listRelatives(sel[0], c=True)[0]
    sg = list(set(cmds.listConnections(shape, type='shadingEngine')))

    for i in sg:
        # list the faces affected by the shader
        fList = cmds.sets(i, q=True)
        # check if our face is in the current shader loop
        if inRange(sel[-1], fList):
            # if True, let's apply this shader to the targets
            for t in target:
                # replace with the name of the new object 
                targetList = [x.replace(sel[0], t) for x in fList]
                # assign shader
                cmds.sets(targetList, e=True, forceElement=i)

# select the face first and the target second
shadeSimilar(target=cmds.ls(sl=True)[1:])
# shadeSimilar(target=['pSphere2', 'pSphere3'])

EDIT :

note that you could use -fl flag in the ls command but in really big meshes, it can be slow

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM