图解NavMesh寻路中的漏斗算法

NavMesh是广泛使用的一种寻路技术,将地图中可走的部分生成连续的多边形/三角形网格,寻路在网格中进行,主要包含两步:1、根据网格的邻接信息构造图,使用A*之类的寻路算法计算出从起点到重点需要走过的多边形/三角形集合;2、使用漏斗算法/拉绳子算法,将多边形列表转换为一条最优的路店。本文主要讲一下对于三角形列表的漏斗算法原理。

诸位读者如果搜索过网络,会发现有一年GDC有人讲了这个算法,也有几篇博客翻译了这个GDC的演讲slides,但多半都是仅仅翻译一遍slides的水平,没有真的把算法说明白,导致笔者在实现这个算法的时候遇到了很大的困难,好在最后还是弄懂了。

阅读本文需要一定的前置知识,您需要知道NavMesh及其对应的三角形网格,以及单位在NavMesh中寻路的三角形列表中间结果。

算法结果

如图所示,假定左边的三角形列表是从寻路算法生成的从起点到终点需要经过的三角形,两个蓝色圆点分别是起点和重点;右边绿色的粗线就是算法的结果,是从起点到终点需要经过的最短路径。

算法过程

  • 首先计算出三角形列表中的邻接边列表,所谓邻接边就是两个三角形公用的边,然后从起点开始,构造到第一条邻接边的漏斗,算法正式开始。

黄色的边均为邻接边,两条绿色的边为初始的漏斗,姑且约定两条“漏斗边”的“起点”为蓝色圆点,方便后文的描述

  • 将两条漏斗边的终点移动到下一条邻接边,对于途中的情况,左边的边没有动(但逻辑上算移动了),右边的边向内收紧了。

分别考虑两条边的角度变化,当漏斗变窄(或不变化)时,本次移动是有效的,否则需要对那条边回退操作,对于图中情况,移动是有效的

可见图中的漏斗变窄了

  • 继续将漏斗边的终点移动到下一条邻接边,漏斗继续收紧,移动有效,之后的两步操作都和上图情况相同

  • 下一步操作出现了第一种特殊情况,漏斗边终点移动到下一条邻接边时,漏斗口的角度变为了负数(原来右边漏斗边转到了左边去),这种情况下,被盖过去的那条边的终点就成为了结果中的第一个点。

同时,将漏斗起点移动到该点,以当前漏斗起点所在三角形的出邻接边构造漏斗,继续算法

  • 使用之前描述的规则继续收紧漏斗口

  • 继续移动漏斗,这一次会发现左边的漏斗边没有移动,而右边的漏斗边会使漏斗口变大,右边的移动是无效的。这次移动只有左边发生了移动(虽然起点和终点一样)

  • 下面是算法的结束情况,算法已经移动到了最后一条邻接边,但是从现在的漏斗底直接连一条线到终点肯定是不可行的。随后我们以终点一个点,当作一条两条端点相同的边。用它继续前进漏斗口。

右边的漏斗边如果移动,会使漏斗口变大,因此不移动,左边的漏斗边移动,会盖过右边的漏斗边,因此右边的漏斗边终点成为了结果中的另一个点。

  • 同样,以该点所在三角形的出邻接边重新构造漏斗,继续算法,很快就会发现漏斗口到终点,收到了最小,算法结束。

原文地址:https://www.cnblogs.com/pointer-smq/p/11332897.html

时间: 2024-10-31 04:03:59

图解NavMesh寻路中的漏斗算法的相关文章

A*算法的寻路中的应用——无阻挡

按照之前转载的文章,自己先实现了下,表示还是很多坑: #include "stdio.h" #include <vector> #include <queue> #include <map> #include <set> using namespace std; int neigor[][2] ={ {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0} }

游戏中的AI算法总结与改进

参考文章: http://games.sina.com.cn/zl/duanpian/2014-03-11/105973.shtml http://www.oschina.net/translate/understanding-steering-behaviors-collision-avoidance?cmp http://blog.csdn.net/ityuany/article/details/5509750 一. 人工智能的定义 人工智能(AI, Artificial Intellige

在A*寻路中使用二叉堆

接上篇:A*寻路初探 GameDev.net 在A*寻路中使用二叉堆 作者:Patrick Lester(2003年4月11日更新) 译者:Panic 2005年3月28日 译者序:     这一篇文章,是"A* Pathfinding for Beginners.",也就是我翻译的另一篇文章<A*寻路初探>的补充,在这篇文章里,作者再一次展现了他阐述复杂话题的非凡能力,用通俗易懂的语句清晰的解释了容易让人迷惑的问题.还是那句话,如果你看了这篇文章仍然无法领会作者的意图,那

在.NET中应用MATLAB算法

在科学研究和工程应用中,往往要进行大量的数学计算,其中包括矩阵运算.这些运算一般来说难以用手工精确和快捷地进行,而要借助计算机编制相应的程序做近似计算.目前流行用Basic.Fortran和c语言编制计算程序, 既需要对有关算法有深刻的了解,还需要熟练地掌握所用语言的语法及编程技巧.对多数科学工作者而言,同时具备这两方面技能有一定困难.通常,编制程序也是繁杂的,不仅消耗人力与物力,而且影响工作进程和效率.为克服上述困难,美国Mathwork公司于1967年推出了"Matrix Laborator

Java中的经典算法之冒泡排序(Bubble Sort)

Java中的经典算法之冒泡排序(Bubble Sort) 原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后.然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后.重复第一趟步骤,直至全部排序完成. 举例说明:要排序数组:int[] arr={6,3,8,2,9,1}; 第一趟排序: 第一次排序:6和3比较,6大于3,交换位置:  

STL笔记(6)标准库:标准库中的排序算法

STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew Austern http://www.cuj.com/experts/1908/austern.htm?topic=experts 用泛型算法进行排序    C++标准24章有一个小节叫“Sorting and related operations”.它包含了很多对已序区间进行的操作,和三个排序用泛型

数字图像处理之快速中值滤波算法

快速中值滤波算法 中值滤波算法: 在图像处理中,在进行如边缘检测这样的进一步处理之前,通常需要首先进行一定程度的降噪.中值滤波是一种非线性数字滤波器技术,经常用于去除图像或者其它信号中的噪声.这个设计思想就是检查输入信号中的采样并判断它是否代表了信号,使用奇数个采样组成的观察窗实现这项功能.观察窗口中的数值进行排序,位于观察窗中间的中值作为输出.然后,丢弃最早的值,取得新的采样,重复上面的计算过程.中值滤波是图像处理中的一个常用步骤,它对于斑点噪声和椒盐噪声来说尤其有用.保存边缘的特性使它在不希

STL中的查找算法

STL中有很多算法,这些算法可以用到一个或多个STL容器(因为STL的一个设计思想是将算法和容器进行分离),也可以用到非容器序列比如数组中.众多算法中,查找算法是应用最为普遍的一类. 单个元素查找 1. find() 比较条件为元素是否相等的查找: template <class InputIterator, class T> InputIterator find (InputIterator first, InputIterator last, const T& val); 2.fi

计算机图形学(二)输出图元_6_OpenGL曲线函数_2_中点画圆算法

中点画圆算法 如同光栅画线算法,我们在每个步中以单位间隔取样并确定离指定圆最近的像素位置.对于给定半径r和屏幕中心(xc,yc),可以先使用算法计算圆心在坐标原点(0, 0)的圆的像素位置,然后通过将xc加到x且yc加到y.从而把计算出的每个位置(x,y)移动到其适当的屏幕位置.在第一象限中,圆弧段从x = 0到x = y,曲线的斜率从0变化到-1.0.因此,可以在该八分圆上的正x方向取单位步长,并使用决策参数来确定每一步两个可能的y位置中,哪一个更接近于圆的位置.然后,其他七个八分圆中的位置可