一、recastnavigation使用介绍


1)模式选择
Solo Mesh:单块生成
Tile Mesh:分块生成
Temp Obstacles:分块并支持动态阻挡
这里测试的话选单块生成
2)模型选择
官方自带3块地图,这里测试选择 nav_test.obj,点击build,生成NavMesh

二、导航网格介绍
- 基础概念介绍
一个导航网格是由多个凸多边形(Convex Polygon, Poly Mesh)组成的。Poly Mesh 有些时候也会简称为 Poly,即上图中的一个个色块部分。 - 单位
在导航网格中的寻路是以 Poly 为单位的。 - 寻路简述
在同个 Poly 中的两点,在忽略地形高度的情况下, 是可以直线到达的;如果两个点位于不同的 Poly,那么就会利用导航网格 + 寻路算法(比如A*算法)算出需要经过的 Poly,再算出具体路径。
1)子集介绍
- 1.
Recast:负责根据提供的模型生成导航网格。 - 2.
Detour:利用导航网格做寻路操作。这里的导航网格可以是 Recast 生成的,也可以是其他工具生成的。 - 3.
DetourCrowd:提供了群体寻路行为的功能。 - 4.
Recast Demo:一个很完善的 Demo,基本上将 Recast 、 Detour 提供的功能都很好地展现了出来。弄懂了这个 Demo 的功能,基本也就了解了 RecastNavigation 究竟可以干什么事。
2)导航网格的生成分为以下几个步骤:(目前生成Navmesh数据主要有两种方式:多边形裁剪和体素化,这里讲体素化)
- 生成navmesh的两种方式
1)多边形裁剪
多边形裁剪是直接对地形的多边形网格数据进行裁剪及合并,从而生成导航网格。方法比较直观,但难度更高,目前havok引擎使用了此方法。
2)体素化
体素化是对地形多边形网格进行栅格化,然后用这些“格子”重新生成导航网格,方法更复杂,但难度更低,Recast使用了此方案,而UE4使用了Recast。
3)recast流程介绍
- 总体概述
将以三角形集合形式表示的空间场景转化为可供寻路使用的导航数据(navmesh)
recast导航网格的生成会分为下面几个步骤:
1、场景模型体素化(Voxelization),或者叫“栅格化”(Rasterization)。
2、过滤出可行走面(Walkable Suface)
3、生成 Region
4、生成 Contour(边缘)
5、生成 Poly Mesh
6、生成 Detailed Mesh
- 部分参数显示
cellSize------x、z方向上的体素精度
walkableSlopeAngle------agent的可行走最大坡度
walkableHeight------agent的可行走的最小高度空间
walkableClimb------agent的可攀爬高度
walkableRadius------agent的行走半径
float* bmin和float* bmax------场景的AABB包围盒
int* tris数组------场景的三角形序列
ntris------场景的三角形个数
float* verts------场景三角形各个顶点的坐标
nverts------场景三角形的顶点总数
- 用图举例

- 上图参数介绍
(如上图这个场景,包含3个三角形和5个顶点)
1)5个顶点的坐标用float* verts[3 * nverts]数组存储,分别表示nverts个顶点的x、y、z坐标,
nverts的值为5;
2)3个三角形用int* tris[3 * ntris]数组存储,分别表示ntris个三角形的3*ntris个顶点在verts数组中
的下标,ntris的值为3。
3)在这个例子中,verts[3 * nverts]数组的内容是
[x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,x5,y5,z5],而tris[3 * ntris]数组的内容是
[0,1,2,1,2,4,2,3,4]。
(1)体素化
-
简单介绍
就是将整个场景模型,都转化为体素(Voxel)。 -
过程介绍
这一步处理和 GPU 渲染管线的光栅化流程概念是一样的,都是将矢量的模型信息(三角形),转化为点阵信息(像素或者体素)。开个脑洞, 假设将来有个全息显示器,可以在一个空间内渲染出制定的模型内容,渲染的最基本单位是体素而不是像素。那么到时的“显卡”很可能就是采取类似的模型体素化过程。

在讲体素化之前,我们先来看下如何将一个凸多边形分隔成两个凸多边形。如下图的五边形,我们分析下 V6-V7 这条切割线分隔凸多边形的流程。


当遍历完所有边之后,我们就得到了两个子凸多边形 V1-V6-V7-V5和V6-V2-V3-V4-V7 。对应的代码为:
convex polygon 凸多边形
// divides a convex polygons into two convex polygons on both sides of a line
static void dividePoly(const float* in, int nin,
float* out1, int* nout1,
float* out2, int* nout2,
float x, int axis)
{
float d[12];
for (int i = 0; i < nin; ++i)
d[i] = x - in[i*3+axis];
int m = 0, n = 0;
for (int i = 0, j = nin-1; i < nin; j=i, ++i)
{
bool ina = d[j] >= 0;
bool inb = d[i] >= 0;
if (ina != inb)
{
float s = d[j] / (d[j] - d[i]);
out1[m*3+0] = in[j*3+0] + (in[i*3+0] - in[j*3+0])*s;
out1[m*3+1] = in[j*3+1] + (in[i*3+1] - in[j*3+1])*s;
out1[m*3+2] = in[j*3+2] + (in[i*3+2] - in[j*3+2])*s;
rcVcopy(out2 + n*3, out1 + m*3);
m++;
n++;
// add the i'th point to the right polygon. Do NOT add points that are on the dividing line
// since these were already added above
if (d[i] > 0)
{
rcVcopy(out1 + m*3, in + i*3);
m++;
}
else if (d[i] < 0)
{
rcVcopy(out2 + n*3, in + i*3);
n++;
}
}
else // same side

本文详尽探讨了RecastNavigation的使用,包括体素化、过滤可行走面、构建高度场、区域划分、轮廓线生成、三角剖分和寻路算法。讲解了从模型到导航网格的转换过程,以及Detour如何利用导航网格进行A*寻路和漏斗算法平滑路径。此外,还讨论了RecastNavigation的局限性和与其他寻路方法的对比。

722

被折叠的 条评论
为什么被折叠?



