How can I set vertex colors with the Maya python api, given a number of uv shells? So for each shell within a single mesh assign a random vertex color. At the bottom I have the previous code which is too slow in more dense meshes.
def setColors():
shells = getUvShelList( cmds.ls(sl=1)[0] )
print ( shells )
"""
#3 similar objects combined into one
{0: ['pCube4.map[0]', 'pCube4.map[1]', 'pCube4.map[2]', 'pCube4.map[3]', 'pCube4.map[4]', 'pCube4.map[5]', 'pCube4.map[6]', 'pCube4.map[7]', 'pCube4.map[8]', 'pCube4.map[9]', 'pCube4.map[10]', 'pCube4.map[11]', 'pCube4.map[12]', 'pCube4.map[13]'],
1: ['pCube4.map[14]', 'pCube4.map[15]', 'pCube4.map[16]', 'pCube4.map[17]', 'pCube4.map[18]', 'pCube4.map[19]', 'pCube4.map[20]', 'pCube4.map[21]', 'pCube4.map[22]', 'pCube4.map[23]', 'pCube4.map[24]', 'pCube4.map[25]', 'pCube4.map[26]', 'pCube4.map[27]'],
2: ['pCube4.map[28]', 'pCube4.map[29]', 'pCube4.map[30]', 'pCube4.map[31]', 'pCube4.map[32]', 'pCube4.map[33]', 'pCube4.map[34]', 'pCube4.map[35]', 'pCube4.map[36]', 'pCube4.map[37]', 'pCube4.map[38]', 'pCube4.map[39]', 'pCube4.map[40]', 'pCube4.map[41]']}
"""
selList2 = om2.MGlobal.getActiveSelectionList()
dagPath = selList2.getDagPath(0)
selMesh = om2.MFnMesh(dagPath)
vertList = list(set(selMesh.getVertices()[1]))
lenVertList = len(vertList)
for shell in shells:
selection_shell = shells.get(shell)
r = [random.random() for i in range(3)]
tempColor = om2.MColor([r[0],r[1],r[2]])
vertexColorList = om2.MColorArray(lenVertList, tempColor)
selMesh.setVertexColors(vertexColorList, vertList)
setColors()
My previous code(too slow):
for shell in chunk:
selection_shell = shells.get(shell)
cmds.select(selection_shell)
facesSel = cmds.polyListComponentConversion(fromUV=True, toFace=True)
cmds.select(facesSel)
r = [random.random() for i in range(3)]
cmds.polyColorPerVertex(facesSel,rgb=(r[0], r[1], r[2]), cdo=1 )
cmds.select(deselect=1)
Here's what I ended up doing, creating a random color per element within a mesh. Similar to element ID in 3ds max.
To answer my own question, I had to convert the UV indices to Vertex indices per shell.
import maya.cmds as cmds
import maya.api.OpenMaya as om
from itertools import zip_longest
from itertools import chain
import random
import colorsys
import time
import maya.mel as mel
class colorVariationShell():
def __init__(self):
self.setSelection()
self.setColors()
def setSelection(self):
# Get the currently selected mesh.
self.mSelList = om.MGlobal.getActiveSelectionList()
self.path = self.mSelList.getDagPath(0)
self.fnMesh = om.MFnMesh(self.path)
def get_progress_bar(self,status_text, max_value):
try:
progress_bar = mel.eval("$tmp = $gMainProgressBar")
except RuntimeError:
progress_bar = None
if progress_bar:
cmds.progressBar(
progress_bar,
edit=True,
beginProgress=True,
isInterruptable=False,
status=status_text,
maxValue=max_value
)
return progress_bar
def getUvShellsOnObj(self):
#Get UV Sets
uvSets = self.fnMesh.getUVSetNames()
for uvset in uvSets:
uvShellIds = self.fnMesh.getUvShellsIds(uvset)[1]
polyVertices = self.fnMesh.getVertices()
polyUvs = self.fnMesh.getAssignedUVs(uvset)
shells = {}
vertexGroup = []
list_zip = zip(polyVertices[1], polyUvs[1])
zipped_list = list(list_zip)
main_progress_bar_3 = self.get_progress_bar("Getting UV Shells IDS", len(zipped_list))
for i, n in enumerate(uvShellIds):
if n in shells:
shells[n].append( i )
else:
shells[n] = [ ( i ) ]
cmds.progressBar(main_progress_bar_3, edit=True, step=1)
cmds.progressBar(main_progress_bar_3, edit=True, endProgress=True)
vertsID = []
uvsID = []
main_progress_bar = self.get_progress_bar("Gathering UV and Vertex Info", len(zipped_list))
for zipItem in zipped_list:
vertsID.append(zipItem[0])
uvsID.append(zipItem[1])
cmds.progressBar(main_progress_bar, edit=True, step=1)
cmds.progressBar(main_progress_bar, edit=True, endProgress=True)
vertex_id_from_shell = {}
main_progress_bar_2 = self.get_progress_bar("Passing UV and Vertex data", len(shells))
for shell in shells:
selection_shell = shells.get(shell)
for idx, item in enumerate(selection_shell):
if item in uvsID:
uv_index = uvsID.index(item)
vertex_ids = vertsID[uv_index]
# if the list does not exist, create it
if shell not in vertex_id_from_shell:
vertex_id_from_shell[shell] = []
# append to list
vertex_id_from_shell[shell].append(vertex_ids)
cmds.progressBar(main_progress_bar_2, edit=True, step=1)
cmds.progressBar(main_progress_bar_2, edit=True, endProgress=True)
return shells, vertex_id_from_shell
def setColors(self):
shells, target_vertex_id = self.getUvShellsOnObj()
#ammount of different colors
var = 3
vertexData = {key : [] for key in range(var)}
pool = []
for val in target_vertex_id.values():
if not pool:
pool = list(range(var))
random.shuffle(pool)
vertexData[pool.pop()].extend(val)
main_progress_bar = self.get_progress_bar("Applying Vertex Colors", len(vertexData))
for vertex_idx, selection_vertex in vertexData.items():
vertexIds = selection_vertex
lenVertList = len(vertexIds)
sat_random = random.uniform(0.5, 1)
increment = 1/len(vertexData)
color_hsv = (vertex_idx*increment, sat_random, vertex_idx*increment+1/len(vertexData))
rgb_color = colorsys.hsv_to_rgb(color_hsv[0],color_hsv[1],color_hsv[2])
final_color = om.MColor(rgb_color)
vertexColorList = om.MColorArray(lenVertList, final_color)
#apply the color
self.fnMesh.setVertexColors(vertexColorList, vertexIds)
cmds.progressBar(main_progress_bar, edit=True, step=1)
cmds.polyOptions(colorShadedDisplay=1)
cmds.progressBar(main_progress_bar, edit=True, endProgress=True)
start_time = time.time()
colorVariationShell()