Выберите подобъекты в Maya Python

В настоящее время я пытаюсь придать каждому подобъекту узла DAG другой цвет. Это работает, когда я выбираю каждый из этих подобъектов/элементов (но не все) в режиме выбора компонента, а затем запускаю над ним скрипт. Но выбор сетки целиком у меня не работает. Я уже пробовал разные виды listRelatives, но ни один из них не работал. Я могу войти в объект и получить каждую вершину, но они не сгруппированы по связности.

    def assignDMat(self,*args):
    #selection = self.selector()
    selection = cmds.ls(selection=True)
    for j in range(0, len(selection)):
        cmds.polyColorPerVertex(selection[j], r=0,  g=0, b=0, cdo=True)
        cmds.polyColorPerVertex(selection[j], r=random.uniform(0,1), cdo=True)

Новый код:

import maya.cmds as cmds
import random

selection = cmds.ls(selection=True)

cmds.polySeparate(selection)


for i in range(0,len(selection)):
    obj=cmds.listRelatives(selection[i])
    print(len(obj))
    for j in range(0,len(obj)-1):
        cmds.polyColorPerVertex(obj[j], r=0,  g=0, b=0, cdo=True)
        cmds.polyColorPerVertex(obj[j], r=random.uniform(0,1), cdo=True)

cmds.polyUnite(("polySurface*"), n="Result", ch=False)

Предполагаемый результат


person Gizmo    schedule 25.11.2019    source источник


Ответы (3)


Использование разделения, а затем повторного слияния мешей может вызвать множество неожиданных проблем, с некоторыми из которых вы уже сталкивались, поэтому лучше этого избегать.

Вместо этого мы можем создать функцию, которая будет возвращать все отдельные оболочки объекта, возвращая кучу списков индексов их лиц. Это можно сделать с помощью cmds.polySelect, чтобы передать ему индекс лица, тогда он выберет всю оболочку. Поскольку оболочка теперь выбрана, мы можем просто собрать новый выбор и продолжить, чтобы получить следующую оболочку. Затем с этим легко просто пройтись по каждому из них и раскрасить их cmds.polyColorPerVertex.

Вот пример, который создаст случайное количество полисфер, объединит их все, а затем установит случайный цвет для каждой оболочки:

import random
import maya.cmds as cmds


# Just makes a bunch of random spheres, combines them, then returns the new mesh.
def make_bunch_of_spheres():
    meshes = []

    for i in range(random.randint(20, 50)):
        meshes.append(cmds.polySphere()[0])
        cmds.move(random.randint(-20, 20), random.randint(-20, 20), random.randint(-20, 20), meshes[-1])

    return cmds.polyUnite(meshes, constructionHistory=False)[0]


def get_shell_faces():
    shells = []  # We'll be putting in lists of face indexes in here later. Each sub-list will represent a separate shell.

    sel = cmds.ls(sl=True)

    for obj in sel:
        faces = cmds.ls(obj + ".f[*]", flatten=True)  # Get all face indexes from the object.

        for face in faces:
            index = int(face.split("[")[1].rstrip("]"))  # Extract the faces index number.
            cmds.polySelect(obj, extendToShell=index)  # Use the face's index to select the whole shell.

            new_faces = cmds.ls(sl=True, flatten=True)  # Now that the shell is selected, capture its faces.
            shells.append(new_faces)  # Append the face's as a new shell.

            # Remove indexes from the new shell from this current loop, to optimize, and to avoid adding duplicate shells.
            for new_face in new_faces:
                if new_face in faces:
                    faces.pop(faces.index(new_face))

    cmds.select(sel)  # Restore selection.

    return shells


# Create a bunch of combined spheres then select it.
new_mesh = make_bunch_of_spheres()
cmds.select(new_mesh)

shells = get_shell_faces()  # Get shells from selection.

# Color each shell!
for shell in shells:
    cmds.polyColorPerVertex(shell, r=random.random(),  g=random.random(), b=random.random(), cdo=True)

Пример

person Green Cell    schedule 26.11.2019
comment
OMG, это работает как шарм, и это именно то, что я искал. Это выглядит намного чище и намного быстрее - person Gizmo; 26.11.2019

import random
obj = cmds.ls(selection=True)
obj_vtx = [cmds.ls(o + '.vtx[*]', fl=True) for o in obj]
for obj in obj_vtx:
    color_id = random.uniform(0,1)
    for vtx in obj:
        cmds.polyColorPerVertex(vtx, r=0,  g=0, b=0, cdo=True)
        cmds.polyColorPerVertex(vtx, r=color_id, cdo=True)

РЕДАКТИРОВАТЬ: поместите цвет в цикл объекта

person DrWeeny    schedule 25.11.2019
comment
К сожалению, это не совсем то, что я ищу. Это дает каждой вершине случайный цвет, но вместо этого мне нужно дать каждому кубу случайный цвет. - person Gizmo; 25.11.2019
comment
вы можете поставить random.uniform на один лопп раньше, чтобы каждая геометрия имела свой случайный цвет. Я отредактировал свой ответ. Не могли бы вы привести пример того, что вы пытаетесь сделать? - person DrWeeny; 26.11.2019
comment
извините, если это недостаточно ясно. Мне как-то нужно получить список всех элементов/подсетей сетки внутри Maya, а затем применить к каждому случайный цвет. простым примером может быть объект TestBox и получение 9 полей внутри списка. Когда я использую команду polySeperate, она разделяет меши, как и должно быть, и я могу задать им случайный цвет. Впоследствии я мог бы использовать polyUnite, чтобы объединить их вместе, но это кажется неправильным подходом. - person Gizmo; 26.11.2019
comment
О, я думаю, я понял, может быть, этот пост может вам помочь: -and-non-destructively/57246797#57246797" title="как я могу эффективно и не деструктивно выполнить присвоение шейдера геоданным"> stackoverflow.com/questions/57236130/ - person DrWeeny; 26.11.2019
comment
Похоже на то, надо завтра проверить. «Большое спасибо - person Gizmo; 26.11.2019
comment
у меня есть решение rn, но имя, поворот и родительские перерывы. Добавил новый код в мой вопрос - person Gizmo; 26.11.2019
comment
На самом деле это довольно медленно делать это для каждой вершины, поэтому вы можете сразу передать все вершины в цвет. - person Green Cell; 26.11.2019
comment
Правда, я просто храню код там, где, как я думал, он случайный для каждой вершины. Также @Gizmo, если вы хотите заполнить свою «поверхность» вершины, используйте диапазон Maya: например: myObjName.vtx[50:103] для заполнения команды, это значительно ускоряет процесс - person DrWeeny; 26.11.2019

В настоящее время рабочее решение. У него нет никаких отказоустойчивых или около того. Например, если у объекта нет родителя, он, вероятно, выдаст ошибку. В моем случае это работает. Большое спасибо за вклад, DrWeeny.

import maya.cmds as cmds
import random

par=cmds.listRelatives(cmds.ls(selection=True),p=True)
selection = cmds.ls(selection=True)
cmds.select(selection)

pivotTranslate = cmds.xform (selection[0], q = True, ws = True, rotatePivot = True)




print(piv)
cmds.polySeparate(selection)


for i in range(0,len(selection)):
    obj=cmds.listRelatives(selection[i])
    print(len(obj))
    for j in range(0,len(obj)-1):
        cmds.polyColorPerVertex(obj[j], r=0,  g=0, b=0, cdo=True)
        cmds.polyColorPerVertex(obj[j], r=random.uniform(0,1), cdo=True)

cmds.polyUnite(("polySurface*"), n=selection[0], ch=False)
cmds.xform (selection[0], ws = True, pivots = pivotTranslate)
cmds.select(par)
cmds.parent(selection[0])
person Gizmo    schedule 26.11.2019
comment
Это ошибка для меня с простым примером объединения двух сфер. - person Green Cell; 26.11.2019