При работе с геометрией меша может появится необходимость назначить каждому вертексу дополнительные свойства или данные, которые должны записываться в blend-файл при сохранении, и к которым нужно иметь доступ.
Однако попытка назначить вертексам нужные данные стандартным способом, через создание кастомных свойств, оборачивается неудачей. Вместо кастомного свойства для вертекса создается лишь кортеж со ссылкой на тип задаваемого свойства.
1 2 3 4 5 6 7 8 9 10 11 |
import bpy class PROP_cls(bpy.types.PropertyGroup): prop: bpy.props.IntProperty(default=1) bpy.utils.register_class(PROP_cls) bpy.types.MeshVertex.prop = bpy.props.PointerProperty(type=PROP_cls) bpy.context.object.data.vertices[0].prop # (<built-in function PointerProperty>, {'type': <class '__main__.PROP_cls'>}) |
Так происходит потому, что задавать кастомные свойства можно только так называемым ID-типам объектов. Это, например, меши, кости, шейдеры, а вот вертексы этому типу не соответствуют, поэтому придать им дополнительные свойства таким способом нельзя.
Казалось бы, проблема не решаема… Но есть же BMesh, который предоставляет гораздо больше возможностей в плане работы с мешами!
Назначить дополнительные свойства вертексам через структуру BMesh напрямую тоже нельзя, при обновлении данных меша из структуры BMesh сохраняться только основные данные. Однако BMesh сам по себе предоставляет возможность пользователю задавать вертексам (а также ребрам, полигонам и лупам) дополнительные данные через систему слоев.
Слой вертексов в BMesh представляет собой массив определенного типа данных с размером, равным количеству вертексов. Каждая ячейка массива привязана к определенному вертексу через ее индекс т.е. ячейка слоя с индексом 0 связана с вертексом с индексом 0, ячейка с индексом 1 – с вертексом с индексом 1 и т.д.
Создав такой слой мы получаем массив ячеек, в которые можем записать нужные нам данные, каждая из которых соответствует своему вертексу.
Для создания слоя вертексов нужно выполнить следующий код:
1 2 3 4 5 6 |
import bpy import bmesh obj_data = bpy.context.object.data bm = bmesh.from_edit_mesh(obj_data) vert_layer = bm.verts.layers.int.new('vert_layer') |
Здесь мы создали слой вертексов с типом “int”, т.е. мы можем задать для каждого вертекса дополнительные данные в виде одного числа целочисленного типа.
Получив слой, можно занести в него нужные данные. Например отметить текущие выделенные вертексы.
1 2 3 4 5 6 |
for v in bm.verts: if v.select: v[vert_layer] = 1 else: v[vert_layer] = 0 bmesh.update_edit_mesh(obj_data) |
Для выделенных вертексов в слой будет записана 1, для не выделенных – 0.
Как мы видим, доступ к данным со слоя вертексов осуществляется из самого вертекса с помощью имени слоя.
1 2 3 |
bm.verts[0]['vert_layer'] # 1 |
Указатель на сам слой можно получить по его имени вызовом функции get()
1 |
bm.verts.layers.int.get('vert_layer') |
Следующий код выведет данные с созданного ранее слоя с выбранными точками:
1 2 3 4 5 6 7 8 9 10 11 |
import bmesh import bpy obj = bpy.context.object bm = bmesh.from_edit_mesh(obj.data) vert_layer = bm.verts.layers.int.get('vert_layer') for v in bm.verts: print(v[vert_layer]) # 1 0 0 1 |