如何用Maya Python API为单个网格的各UV壳设置随机顶点颜色
为多UV壳网格高效分配随机顶点颜色(Maya Python API实现)
问题背景
当单个网格包含多个UV壳时,需要为每个UV壳分配随机顶点颜色。此前基于cmds的实现在高密度网格下运行速度极慢,现需通过Maya Python API实现高效方案。
当前尝试的代码
import maya.api.OpenMaya as om2 import random 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()
此前慢速的cmds实现
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)
高效实现方案
当前尝试的代码存在两个核心问题:一是每次循环都会覆盖所有顶点的颜色,最终只有最后一个UV壳的颜色生效;二是多次调用setVertexColors导致API开销过大。以下是优化后的实现:
优化代码
import maya.api.OpenMaya as om2 import random def get_uv_shell_vertices(mesh_dag, uv_components): """从UV壳的UV组件列表中提取对应的顶点ID(自动去重)""" mesh_fn = om2.MFnMesh(mesh_dag) vertex_ids = set() for uv_comp in uv_components: # 解析UV组件字符串,提取UV索引 uv_index = int(uv_comp.split('[')[-1].rstrip(']')) # 获取该UV关联的所有顶点 _, vert_ids = mesh_fn.getAssociatedFacesAndVerticesForUV(uv_index) vertex_ids.update(vert_ids) return list(vertex_ids) def setColors(): # 获取选中的网格对象 sel_list = om2.MGlobal.getActiveSelectionList() if sel_list.length() == 0: om2.MGlobal.displayError("请选择一个网格对象") return dag_path = sel_list.getDagPath(0) mesh_fn = om2.MFnMesh(dag_path) mesh_name = om2.MFnDagNode(dag_path).name() # 获取UV壳列表(假设getUvShelList已实现,返回{壳ID: [UV组件列表]}) shells = getUvShelList(mesh_name) if not shells: om2.MGlobal.displayWarning("未检测到UV壳") return # 获取网格所有顶点ID,初始化颜色数组 all_vertex_ids = list(set(mesh_fn.getVertices()[1])) color_array = om2.MColorArray(len(all_vertex_ids), om2.MColor([0, 0, 0])) # 为每个UV壳分配随机颜色 for _, uv_components in shells.items(): shell_verts = get_uv_shell_vertices(dag_path, uv_components) # 生成随机RGB颜色 rand_color = om2.MColor([random.random(), random.random(), random.random()]) # 更新颜色数组中对应顶点的颜色 for vid in shell_verts: color_array[vid] = rand_color # 一次性设置所有顶点颜色,大幅降低API调用开销 mesh_fn.setVertexColors(color_array, all_vertex_ids) om2.MGlobal.displayInfo("顶点颜色分配完成") setColors()
优化说明
- 减少API调用:仅调用一次
setVertexColors完成所有顶点颜色设置,避免多次调用的开销 - 避免颜色覆盖:通过预初始化颜色数组,逐个更新对应UV壳顶点的颜色,确保每个壳的颜色都能保留
- 高效顶点映射:直接通过Maya API获取UV关联的顶点,避免
cmds选择、组件转换等冗余操作 - 自动去重:用集合存储顶点ID,避免重复设置同一顶点的颜色
内容的提问来源于stack exchange,提问作者johancc
相关产品推荐
相关产品推荐

