[Работа с 3D-графикой] Работа с 3D моделями в Python с использованием библиотеки OpenMesh

Автор Сообщение
news_bot ®

Стаж: 6 лет 7 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
02-Май-2021 18:31

Есть очень удобная и мощная библиотека, которая значительно упрощает работу с полигональными 3D моделями или мешами под названием OpenMesh. Она предоставляет широкий набор операций для работы с 3D моделями и имеет версию в Python. В этой статье я покажу как работать с 3D моделями используя обертку OpenMesh для Python. Кому интересно, прошу под кат.Начало работы с OpenMeshИзначально OpenMesh написан на C++, но имеет оберткуна языке Python, которую можно использовать для быстрой и легкой разработки. Давайте посмотрим какие операции предоставляет эта обертка.Для начала установим пакет с помощью pip:
pip install openmesh
Создадим новый Python скрипт и импортируем модуль openmesh
import openmesh as om
import numpy as np
Создадим объект, представляющий 3D меш
mesh = om.TriMesh()
Добавим несколько вершин
# add a a couple of vertices to the mesh
vh0 = mesh.add_vertex([0, 1, 0])
vh1 = mesh.add_vertex([1, 0, 0])
vh2 = mesh.add_vertex([2, 1, 0])
vh3 = mesh.add_vertex([0,-1, 0])
vh4 = mesh.add_vertex([2,-1, 0])
и несколько полигонов
fh0 = mesh.add_face(vh0, vh1, vh2)
fh1 = mesh.add_face(vh1, vh3, vh4)
fh2 = mesh.add_face(vh0, vh3, vh1)
В OpenMesh вершина представлена объектом VertexHandle. Объекты VertexHandle передаются во многие методы библиотеки OpenMesh в качестве параметра. Есть также альтернативный способ через питоновский список вершин
vh_list = [vh2, vh1, vh4]
fh3 = mesh.add_face(vh_list)
Стоит отметить, что OpenMesh также вводит специальный тип элемента в модели под названием Half-edge. Я не буду его рассматривать в данной статье. Подробнее о нем можно почитать здесь.Манипуляция с отображением текстуры и координатами вершинЯ не буду раскрывать тему отображения текстуры (texture mapping) полигонов. Читатель может прочитать детальное объяснение этой темы здесь.Получим координаты текстуры (UV texture coordinates) вершины:
tc = mesh.texcoord2D(vh)
tc представляет собой tuple. Значения координат u и v можно получить по индексу 0 и 1 соответственно.Изменим координаты текстуры
uv_coords = [0.5, 0.2]
mesh.set_texcoord2D(vh, uv_coords)
Здесь vh - объект типа VertexHandle.Получим точку с координатами вершины
point = mesh.point(vh)
point представляет собой tuple. Координаты точки можно получить по индексу 0 и 1
x, y = tc[0], tc[1]
Можно получить все точки вершин модели
point_array = mesh.points()
и использовать их для сдвига модели вдоль оси (например X)
point_array += np.array([1, 0, 0])
Важные замечания по работе с OpenMeshНе советую использовать enumerate() при итерировании вершин в цикле. Вы можете получить неожиданное поведение, например одинаковые координаты текстуры UV для разных вершин.При сохранение меша в файл OpenMesh по умолчанию не сохраняет координаты текстур для вершин (vt строки) в файле obj. Чтобы решить эту проблему нужно передать параметр vertex_tex_coord в метод write_mesh (источник):
om.write_mesh(‘test_out.obj’, mesh, vertex_tex_coord=True)
Также OpenMesh не сохраняет файл материалов mtl в файле obj. Для сохранения информации о материале используйте параметр face_color при чтении файла obj
mesh = openmesh.read_trimesh('test.obj', vertex_tex_coord=True, face_color=True)
и записи в файл
openmesh.write_mesh('test_out.obj', mesh, vertex_tex_coord=True, face_color=True)
То же касается и нормалей. Чтение модели obj с нормалями
mesh = openmesh.read_trimesh('test.obj', vertex_normal=True)
и записи в файл
openmesh.write_mesh('test_out.obj', mesh, vertex_normal=True)
Здесь важно использовать одинаковые параметры и при чтении и при записи. Например, если мы хотим получить и сохранить информации о материале нужно использовать параметр face_color в обоих методах read_trimesh и write_mesh.При работе с OpenMesh я сделал интересное наблюдение: порядок индексов координат текстур вершин (индексы строк vt) меняется. Например для такой строки в исходном файле obj
f 1/1 2/2 3/3
Соответствующая строка в выходном файле obj может выглядеть примерно так
f 1/3 2/1 3/2
Итерации и циклыИтерации над вершинами в меше
for vh in mesh.vertices():
    print(vh.idx())
Цикл for возвращает объекты vh типа VertexHandle. idx() возвращает индекс вершины.Итерации над полигонами и гранями
# iterate over all edges
for eh in mesh.edges():
    print eh.idx()
# iterate over all faces
for fh in mesh.faces():
    print fh.idx()
Аналогично итератору над вершинами цикл for возвращает объекты fh типа FaceHandle.Итерация над всеми half-edge в меше
for heh in mesh.halfedges():
    print heh.idx()
Над вершинами соседними с заданной
for vh_n in mesh.vv(vh):
    print(vh_n.idx())
Над гранями выходящими из заданной вершины
for eh in mesh.ve(vh1):
    print eh.idx()
Над полигонами, смежными с заданной вершиной
for fh in mesh.vf(vh1):
    print fh.idx()
Все то же самое можно проделать и с полигоном
# iterate over the face's vertices
for vh in mesh.fv(fh0):
    print vh.idx()
# iterate over the face's halfedges
for heh in mesh.fh(fh0):
    print heh.idx()
# iterate over the face's edges
for eh in mesh.fe(fh0):
    print eh.idx()
# iterate over all edge-neighboring faces
for fh in mesh.ff(fh0):
    print fh.idx()
Это все. Не так сложно, не правда ли. Удачи вам в работе с 3D мешами с использованием OpenMesh и до новых встреч.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_rabota_s_3dgrafikoj (Работа с 3D-графикой), #_3d_modelirovanie (3d моделирование), #_cad, #_mesh, #_3d_model, #_triangle, #_rabota_s_3dgrafikoj (
Работа с 3D-графикой
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Сен 04:18
Часовой пояс: UTC + 5