OpenMesh, децимация, Линдстрем-Тёрк

В моем приложении я работаю с большим количеством треугольных сеток, и иногда мне нужно уменьшить количество треугольников в них (свернуть некоторые ребра). Для обработки сетки я использую openmesh (openmesh.org), так как он современный (C++), но в основном потому, что он не тащит с собой огромное количество зависимостей (зависит только от C++ std, и любой современный компилятор может с этим справиться (мне нужно быть кроссплатформенным). Linux/Windows/Mac OSX)).

Теперь мне нужно уменьшить (decimate в терминологии openmesh) некоторые сетки, но мне нужно сохранить границы. (рассматриваемые сетки изначально были сеточными (512x512), но в центре их были вытянуты/добавлены некоторые выпуклые элементы, важно, чтобы после уменьшения внешние края сетки по-прежнему образовывали прямоугольник)

Я не вижу никакого способа децимировать их в openmesh и сохранить объем/контур, все модули децимации OpenMesh::Decimater::Mod* используют квадрики в качестве основы.

В GTS (GNU Triangulated Surface Library) реализована редукция Линдстрема-Тёрка, которая идеально подходит для моих нужд (я сделал грязную оболочку, чтобы проверить, нужна ли она мне), и она работает, но с GTS есть проблемы - это не многопоточное сохранение (я сокращаю количество сеток в нескольких потоках), а с GTS это невозможно, поскольку он использует глобальные переменные внутри библиотеки для отключения/включения некоторых вещей при уменьшении сетки:/) (а также перетаскивает весь glib как его зависимости)

Есть еще CGAL и в нем тоже реализован Lindstrom-Turk, но он тащит за собой весь буст и прочие зависимости :/

Есть ли какой-нибудь модуль прореживания для openmesh, который выполняет прореживание с сохранением границы/объема? (Я искал, но не нашел :/)


person user2441788    schedule 11.01.2015    source источник
comment
Обратите внимание, что в последней версии CGAL (4.5) вы можете напрямую применять алгоритм упрощения к OpenMesh HDS без необходимости конвертировать его в CGAL HDS. Единственными зависимостями, требуемыми CGAL, являются boost и GMP.   -  person sloriot    schedule 12.01.2015
comment
'только' boost:] - вот почему я спрашиваю... Я пытаюсь избежать зависимости от повышения...   -  person user2441788    schedule 12.01.2015
comment
Любопытно, почему наличие boost в качестве зависимости является такой проблемой?   -  person sloriot    schedule 16.01.2015


Ответы (1)


Насколько я понимаю, под «границами сетки» вы подразумеваете ребра сетки, которые образуют только одну грань сетки (например, внешние края сетки 512x512 в вашем примере), в отличие от более распространенного случая, когда каждое ребро сетки совместно используется двумя или более граней сетки.

В OpenMesh на самом деле есть довольно простой способ сказать модулю OpenMesh::Decimater сохранить эти ребра как есть. Более того, это не зависит от типа используемого вами модуля прореживания. Фактическая структура данных сетки (т.е. OpenMesh::TriMesh_ArrayKernelT<>) имеет функцию, называемую «блокировкой вершин». По сути, это способ сказать OpenMesh не касаться определенного набора вершин, независимо от того, что происходит во время прореживания.

Вот фрагмент кода из официальной документации. , немного изменено для С++ 11:

using Mesh = OpenMesh::TriMesh_ArrayKernelT<>;

void protectMeshBoundariesFromDecimation(Mesh& mesh) {
   mesh.request_vertex_status();

   for (const auto& halfEdgeHandle : mesh.halfedges()) {
      if (mesh.is_boundary(halfEdgeHandle) ) {
         mesh.status(mesh.to_vertex_handle(halfEdgeHandle)).set_locked(true);
         mesh.status(mesh.from_vertex_handle(halfEdgeHandle)).set_locked(true);
      }
   }
}

Если вы хотите прочитать полные документы по этому вопросу, а приведенная выше ссылка больше не работает, в дереве содержимого документации перейдите в раздел OpenMesh -> Документация OpenMesh -> Документация по инструментам OpenMesh -> Структура прореживания сетки.

По сути, это зацикливается на всех полуребрах (не ребрах!) вашей сетки и «блокирует» вершины, которые образуют полуребра, у которых нет пары (нет второго полуребра). Благодаря природе полуреберных структур данных, которые использует OpenMesh, это имеет сложность O(n) для сетки из n ребер.

Если вы не знакомы со спецификой полуреберных структур данных, я бы посоветовал прочитать отличный документ "Использование и понимание OpenMesh" вводный раздел документации OpenMesh.

person Sergey Nikitin    schedule 18.10.2015