OpenMesh, decimation, Lindstrom-Turk



在我的应用程序中,我正在使用很多三角形网格,有时我需要减少其中三角形的数量(使一些边缘失效)。对于网格处理,我使用 openmesh (openmesh.org),因为它是现代的 (C++),但主要是因为它不会拖拽大量的依赖项(仅依赖于C ++ std,任何现代编译器都可以处理它(我需要跨平台的Linux/Windows/Mac OSX))。

现在我需要减少(在开放网格术语中减少)一些网格,但我需要保留边框。(有问题的网格是原始网格(512x512),但在它们的中心,一些凹陷元素被挤压/添加,在缩小后网格的外边缘仍然形成矩形至关重要)

我看不出有任何方法可以在 openmesh 中摧毁它们并保留体积/轮廓,所有 OpenMesh::D ecimater::Mod* 抽取模块都使用二次图作为基础。

在GTS(GNU三角化表面库)中,实现了Lindstrom-Turk缩减,非常适合我的需求(我做了一些脏包装器来测试它是否是我想要的),它可以工作,但是使用 GTS 存在问题 - 它不是多线程保存(我正在减少多个线程上的许多网格),并且使用 GTS 这是不可能的,因为它使用库中的全局变量来禁用/启用一些东西同时减少网格:/)(它也拖了整个glib,因为它是依赖项)

还有 CGAL,它也实现了 Lindstrom-Turk,但它拖累了整个提升和其他依赖项:/

是否有任何用于 openmesh 的抽取器模块可以在边界/体积保留的情况下进行抽取?(我搜索过,但没有找到:/)

据我了解,"网格边界"是指仅形成单个网格面的网格边缘(如示例中 512x512 网格的外边缘),而不是更常见的情况,即每个网格边缘在 2 个或多个网格面之间共享。

在OpenMesh中,实际上有一种非常简单的方法可以告诉OpenMesh::Decimater模块按原样保留这些边缘。更好的是,它不依赖于您实际使用的抽取模块类型。实际网格数据结构(即 OpenMesh::TriMesh_ArrayKernelT<> )具有称为"顶点锁定"的功能。它本质上是一种告诉OpenMesh无论在抽取过程中都不要接触一组特定顶点的方法。

以下是直接来自官方文档的代码片段,在 C++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 Tools Documentation -> Mesh 抽取框架

从本质上讲,这会循环网格的所有半边(不是边!),并"锁定"形成没有对(没有第二个半边)的半边的顶点。由于OpenMesh使用的半边数据结构的性质,这对于n边网格来说O(n)复杂性。

如果您不熟悉半边数据结构的细节,我建议您通读OpenMesh文档的优秀"使用和理解OpenMesh"介绍部分。

相关内容

  • 没有找到相关文章

最新更新