У вертексов нет свойства “цвет”. Цвета вертексов, задаваемые раскраской в режиме Vertex Paint или любым другим способом, хранятся в атрибуте – отдельном списке значений. Для того чтобы выделить точку по цвету, назначенному ей в атрибуте, нужно связать индексы атрибута с индексом вертекса.
Прямой связи между индексом вертексов и индексами цветов в атрибуте тоже нет. Так сделано потому, что одна точка может иметь более чем один цвет.
Например, возьмем два смежных полигона и раскрасим их в фиолетовый и голубой цвета. Какой цвет в этом случае должен быть назначен вертексам с индексами 0 и 3 – голубой или фиолетовый? Назначение вертексу только одного цвета исказит цвет полигона в целом.
Для того чтобы избежать подобной неоднозначности на смежных полигонах, цвета вертексам назначаются не по их индексам, а по индексам “лупов” (loop) полигонов.
Меш, состоящий из двух смежных полигонов, имеет 6 вертексов с индексами от 0 до 5, и в то же время, каждый его полигон имеет по 4 лупа с индексами от 0 др 7.
1 2 |
bpy.context.object.data.loops[:] # [bpy.data.meshes['Plane'].loops[0], bpy.data.meshes['Plane'].loops[1], ... bpy.data.meshes['Plane'].loops[7]] |
В данном случае для вертекса с индексом 0 голубой цвет назначается лупу с индексом 0, а фиолетовый цвет – лупу с индексом 5. Для вертекса с индексом 3 голубой цвет назначается лупу с индексом 3, а фиолетовый – лупу с индексом 6.
Таким образом каждый вертекс может иметь несколько цветов, точнее столько, скольким полигонам этот вертекс принадлежит.
У меша может быть несколько независимых раскрасок, распределенных по слоям. Список слоев, каждый со своей раскраской, хранится в параметре vertex_colors.
1 2 |
bpy.context.object.data.vertex_colors[:] # [bpy.data.meshes['Plane'].vertex_colors["Attribute"]] |
Текущий активный слой можно получить через параметр active:
1 2 |
bpy.context.object.data.vertex_colors.active # bpy.data.meshes['Plane'].vertex_colors["Attribute"] |
Список самих цветов мы можем получить из параметра data:
1 2 3 4 5 6 7 8 |
for data in bpy.context.object.data.vertex_colors.active.data: print(data.color[:]) # (0.0, 1.0, 1.0, 1.0) # (0.0, 1.0, 1.0, 1.0) # (1.0, 0.0, 0.0, 1.0) # (1.0, 0.0, 0.0, 1.0) # ... |
Имея полный список цветов для всех точек, мы можем пройти по всем лупам полигонов, получить нужные индексы, и по этим индексам получить цвета, соответствующие вертексам меша.
Сначала пройдем в цикле по всем полигонам:
1 |
for i, polygon in enumerate(bpy.context.active_object.data.polygons): |
и для каждого полигона по индексам лупов:
1 |
for i1, loopindex in enumerate(polygon.loop_indices): |
По индексу лупа мы можем получить данные о цвете для активного слоя:
1 |
dolor_data = bpy.context.active_object.data.vertex_colors.active.data[loopindex] |
и, например, выделить те вертексы, которые хотя бы для одного полигона окрашены в красный цвет:
1 2 3 4 |
if dolor_data.color[0] > 0.99 \ and dolor_data.color[1] < 0.09 \ and dolor_data.color[2] < 0.09: bpy.context.active_object.data.vertices[bpy.context.active_object.data.polygons[i].vertices[i1]].select = True |
Для сравнения компонентов цвета можно использовать и полное равенство (знак ==), но лучше элементы сравнения > и <, чтобы избавиться от неточности для чисел с плавающей точкой.
Полный код, при помощи которого можно выделить все вертексы текущего активного меша, окрашенные в красный цвет:
1 2 3 4 5 6 7 8 |
meshdata = bpy.context.active_object.data for i, polygon in enumerate(meshdata.polygons): for i1, loopindex in enumerate(polygon.loop_indices): dolor_data = meshdata.vertex_colors.active.data[loopindex] if dolor_data.color[0] > 0.99 \ and dolor_data.color[1] < 0.09 \ and dolor_data.color[2] < 0.09: meshdata.vertices[meshdata.polygons[i].vertices[i1]].select = True |