如何高效且非破坏性地对地理区域执行着色器分配?

How can I perform shader assignment to a geo efficiently and non-destructively?

我的目标是为地理区域的每个部分设置一个着色器。 geo 的部分通常是一组附加的面。我这样做是为了烘焙 ID 贴图,然后在 Substance Painter 中使用它。

到目前为止,我将各个部分分开,然后为每个部分分配一个着色器并将它们重新组合起来。我最终删除了历史记录以清理大纲和网格本身。

import maya.cmds as mc
import random

selection = mc.ls(sl=True)[0]
parent = mc.listRelatives( selection, ap = True)[0]
mc.polySeparate(selection)
parts = mc.ls(sl=True)

for p in parts:
    sha = mc.shadingNode('lambert', asShader=True, name=p+"_lambert")
    sg = mc.sets(empty=True, renderable=True, noSurfaceShader=True,  name=p+"_SG")
    mc.setAttr(sha+".color", random.uniform(0.0, 1.0), random.uniform(0.0, 1.0), random.uniform(0.0, 1.0))
    mc.connectAttr( sha+".outColor", sg+".surfaceShader", f=True)
    mc.sets(p, e=True, forceElement=sg)

result = mc.select( selection, r = True )
sel = mc.ls( sl=True )
parts = mc.listRelatives( sel[0], c = True )
mc.polyUnite(parts, muv = True, name = selection)
mc.DeleteHistory()

我已经在零件上设置了我的着色器,但丢失了我的原始组,网格在该组下是父级的,这样做感觉不对。

有没有办法在不使用 'separate' 的情况下创建多组零件并为每组分配一个着色器?

我假设您在组合对象上分配着色器,但我的脚本应该给您想法:(运行 它会在组合球体上分配随机着色器)

只是为了恢复我列出所选对象的面孔。 我拿一张脸,增加选择直到它不能再 为它们分配一个着色器,从主列表中删除选择的面 然后再循环一次 最后,我通过为每个对象创建一个集合和为每个分配的兰伯特

创建子集来生成某种历史记录
import maya.cmds as cmds
import random

def growComponent(component):
    # component = vertices[0]
    check = component.split('.')
    if len(check) != 2:
        cmds.error('please select one component in order to grow the selection')

    mySel = [component]
    counterSel = len(cmds.ls(component, fl = True))
    myFinalSel = 0

    while myFinalSel != counterSel:
        mySel = component
        counterSel = len(mySel)
        vert = cmds.polyListComponentConversion(mySel, tv = True)
        component = cmds.polyListComponentConversion(vert, tf = True)
        component = cmds.ls(component, fl = True)
        myFinalSel = len(component)

    component = cmds.polyListComponentConversion(component, tv = True)
    return component

# =========================
#just to illustrate an exemple selection of 10 sphere combined
psph = [cmds.polySphere()[0] for i in range(10)]
for i in psph:
    cmds.setAttr(i+'.t', random.uniform(0.0, 3.0), random.uniform(0.0, 3.0), random.uniform(0.0, 3.0))
sph_comb = cmds.polyUnite(psph)
cmds.delete(sph_comb, ch=True)
# ===============================


selection = cmds.ls(sph_comb)[0]

faceSet = cmds.sets(em = True, name = '{}_sg_faceset'.format(selection))

combinedFaceGrp = cmds.ls(selection + '.f[:]', fl = True)

partsFace = []
x = 0
while combinedFaceGrp or x>10000:

    len(combinedFaceGrp)
    component = growComponent(combinedFaceGrp[0])
    faces = cmds.polyListComponentConversion(component, tf = True)
    partset = cmds.sets(faces, name='part{}_{}_set'.format(x, selection))
    cmds.sets(partset, edit = True, fe = faceSet)
    x+=1

    # remove face selected
    faces_fl = cmds.ls(faces, fl=True)
    combinedFaceGrp = list(set(combinedFaceGrp)-set(faces_fl))

    # assign shader
    sha = cmds.shadingNode('lambert', asShader=True, name="{}_{}_lambert".format(selection, x))
    sg = cmds.sets(empty=True, renderable=True, noSurfaceShader=True,  name="{}_{}_sg".format(selection, x))
    cmds.setAttr(sha+".color", random.uniform(0.0, 1.0), random.uniform(0.0, 1.0), random.uniform(0.0, 1.0))
    cmds.connectAttr( sha+".outColor", sg+".surfaceShader", f=True)
    cmds.sets(faces, e=True, forceElement=sg)