OpenMesh,抽取,Lindstrom-Turk

时间:2015-01-11 09:25:21

标签: mesh triangulation reduction openmesh

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

现在我需要减少(在openmesh术语中抽取)一些网格,但我需要保留边框。 (所讨论的网格原始是网格(512x512),但在它们的中心,一些褶皱元素被挤压/添加,重要的是在缩小后,网格的外边缘仍然形成矩形)

我没有看到任何方法在openmesh中抽取它们并保留音量/轮廓,所有OpenMesh :: Decimater :: Mod *抽取模块都使用quadric作为基础。

在GTS(GNU Triangulated Surface Library)中实现了Lindstrom-Turk减少,非常适合我的需求(我做了一些脏包装来测试它是否是我想要的)并且它有效, 但是使用GTS存在问题 - 它不是多线程保存(我在多个线程上减少了很多网格)而且使用GTS它是不可能的,因为它使用库中的全局变量来禁用/启用 减少网格时的一些东西:/)(并且它也拖动整个glib作为它的依赖)

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

是否有openmesh的抽取模块可以通过边框/体积保存进行抽取? (我搜索过,但没有找到:/)

1 个答案:

答案 0 :(得分:1)

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

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

这是一个直接来自official documentation的代码片段,对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 - &gt; OpenMesh文档 - &gt; OpenMesh工具文档 - &gt;网格抽取框架

基本上,这会在网格的所有半边(不是边缘!)上循环,并“锁定”形成没有对的半边(没有第二个半边)的顶点。由于OpenMesh使用的半边数据结构的性质,O(n)边的网格具有n复杂度。

如果您不熟悉半边数据结构的细节,我建议您仔细阅读OpenMesh文档的优秀"Using and understanding OpenMesh"介绍部分。