NavMesh生成研究(五):细节网格生成

本文翻译自:http://critterai.org/projects/nmgen_study/detailgen.html

这篇文章描述了构造导航网格过程中的第五步,也就是最后一步:带有高度细节信息的三角网格的生成

源数据类:PolyMeshFieldOpenHeightField
构造类:DetailMeshBuilder
数据类:TriangleMesh

如果你需要回忆这一步的大致过程,请回到总体概述。

为什么需要这一步

如果源网格的可行走表面被投影到xz平面上,且被前一个步骤中生成的多边形网格覆盖,那么这两者能很好地匹配。但是在3维空间中,多边形网格可能不会与源网格的高度轮廓恰好一致。这一阶段增加了高度细节,使得细节网格能够在三维上匹配源网格的表面。为了实现这个目标,我们遍历所有的多边形,只要多边形过度偏离源网格,就在多边形的边和内部插入顶点。

在下面的例子中,靠近楼梯的多边形网格在xz平面上匹配,但是在y轴上偏离了很多。

这里写图片描述

当高度细节加入后,在y轴上匹配得更好了。

这里写图片描述

从技术上来说,这一步对于寻路不是必需的。我们真正所需的只是一个凸多边形网格,它用来生成寻路算法相关的图——上一阶段中创建的多边形网格已经提供了所有必要的数据。某些场合尤其如此——例如使用物理或者射线将寻路代理放置在源网格的表面上。事实上,Recast Navigation的Detour库只使用了多边形网格做寻路。当前步骤中生成的高度细节是可选的,若包括进去,则只是用于优化各种Detour函数计算出的顶点位置。

同时需要注意的是,这个过程也只是生成对原始网格表面的一个更好估算。体素化决定了无法得到完全精确的位置。除此以外,考虑到性能和内存的影响,高度细节过多往往会比过少更糟糕。

第一步:高度补丁(height patch)

你这样就以为无需体素空间和高度域了?不完全是这样。为了加入高度细节,我们需要能够确定多边形的表面是否与覆盖它的开放高度域区间离得足够远。高度补丁就是用于这个目的。它包含与一个多边形相交的每个开放高度域格子位置的期望高度。基本上,它是开放高度域某一部分的简单裁剪,带有下列特征:

  • 它只包含单个多边形的AABB包围盒的高度信息。
  • 它只包含每个格子位置的底部高度(无区间)。
  • 它只对每个格子位置有单个高度(无覆盖)。

这里写图片描述

总览

当前阶段的主要步骤如下:对于每个多边形来说,

  1. 对多边形的外边采样。若这条边偏离高度补丁大于contourMaxDeviation值,则添加顶点。
  2. 对多边形执行德劳内三角化(Delaunay triangulation)。
  3. 对多边形的内部表面采样。若表面偏离高度补丁大于contourMaxDeviation值,则添加顶点。对于任何新顶点更新三角化。

    给多边形的边添加细节

这一步更好地匹配数据在高度补丁里的多边形的边的高度。它是两个采样过程的第一步,第二步是处理多边形表面。

接下来从2D角度看。在下面一组图中,我们从沿y轴上升的那一侧来看网格。

对于多边形的每条边:基于contourSampleDistance的值将边切割成线段。例如:如果边长10个单位,采样距离是2个单位,那么将边切割成5条等长的线段。这里的“采样顶点”并非全部会被用到,它们只是可能的顶点。

这里写图片描述

使用高度补丁数据,将每个采样顶点的高度(y值)快照到高度域中。

这里写图片描述

检查采样顶点到原始边之间的距离。若超过最大偏离,则插入离原始边最远的采样顶点。

这里写图片描述

重复距离检查,直到多边形新的部分已完成。

这里写图片描述

三角化

网上有大量关于德劳内三角化的信息,因此我们不再赘述,唯一想说的就是:在给边添加细节后,它被用来对多边形做三角化。到此为止原始多边形不复存在。所有的操作都是针对三角形网格。

这是多个可能的三角化的第一步。从这一步开始,当任意新的顶点加入到网格中时,三角化将会发生。

给内部多边形表面添加细节

到此为止我们从单个多边形得到了较小的三角形网格。(或者,如果原始的多边形就是三角形,而且没有新的顶点在边的细节这一步加入,那么我们仍然拥有一个三角形。)所有的顶点仍然在网格的边上。在这一步中,我们检查网格的内部表面,看它是否与高度补丁中的数据偏离太多。

这里写图片描述

下面一组图仍然是2D的。但是我们切换到xz平面的俯视视角。

添加高度细节到三角形网格的内部表面与添加到边上类似。采样顶点的格子沿着网格的AABB包围盒所在的xz平面被构建。间距基于contourSampleDistance的值。采样顶点的y轴的值被快照存储到高度补丁里的数据中。

网格外部的采样顶点被丢弃掉。

这里写图片描述

在剩余的采样顶点中,找到离三角形网格的表面最远的那个。如果它比contourMaxDeviation的值更远,那么就将它加入网格中,并重新三角化。

这里写图片描述

重复这个过程,直到再没有采样顶点超过contourMaxDeviation的值。

这里写图片描述

结尾

这一步中的其他工作属于事务性工作。由独立多边形创建的细节三角形网格被合并成单个网格,并被加载到TriangleMesh的实例中。整个过程就此完结。我们得到了最终的导航网格。

这里写图片描述

猜你喜欢

转载自blog.csdn.net/needmorecode/article/details/81915785