游戏寻路之平滑路径—拉绳(漏斗)

拉绳算法(漏斗算法)平滑路径

文章以Recast-Detour(JAVA版本)中的String Pulling作为学习研究的基本源码

JAVA版本中的方法名称为:findStraightPath() 方法


目录

1. 算法概述

2. 算法详解

3. 算法思考


算法概述

游戏寻路之平滑路径—拉绳(漏斗)_第1张图片

上图为三角形导航网格,S为寻路起点,End为寻路终点。

游戏寻路之平滑路径—拉绳(漏斗)_第2张图片

该图为基础A星算法寻路后的多边形路径,其中A星算法是以三角形边中点作为距离运算的迭代点的。

游戏寻路之平滑路径—拉绳(漏斗)_第3张图片

该图为漏斗算法优化后的路径点,最终为S,D,G,End。可以明显的看出基础A星在非规整导航网格中的路径结果是不平滑的,有种左右摇摆的感觉,而漏斗算法就是解决路径平滑问题的。

算法详解

所谓漏斗,就是设定两个边界包围向量,然后去迭代路径多边形,如果迭代的过程中,这两个边界包围向量可以不断缩小,证明这些路径多边形是可以直线联通的,这就是所谓的拉绳。而一旦出现了边界向量的交叉,则证明出现了拐角点。

 

游戏寻路之平滑路径—拉绳(漏斗)_第4张图片

  • S为起始点,序号①到⑨为A星寻路的结果多边形路径。End为终点。
  • 初始多边形为①,下一个路径为②,①②之间的连接边是CB。
  • 初始两个空间范围向量,图中的SB,SC。为了方便,下面称SB为“范围右边界”,SC为“范围左边界”。
  • ②和③的临边是CE,根据CE端点构造新的“范围左右边界”SC、SE。后续的算法就是不断的迭代对比,新边界和旧边界的关系。

“范围左右边界”并不是随意定义的,是需要遵循规则的。在DETOUR中,一个多边形的边采用的逆时针存储方式,例如多边形①,三点的存储方式为,CBA,这是严格控制的。而两个边界向量,在区分左右边界的时候,是根据两个相邻多边形公共边的方向顺序来定的。

  • 确定左右边界的时候,是根据公共边在“初始多边形”中的边端点顺序来的。
  • 从①到②,①就是“起始多边形”,DETOUR中称为“From”,②就是“目的多边形”,DETOUR中称为“To”。
  • 例如,①②的公共边为CB,CB在①中的定义顺序,按照逆时针来,C就是左边界点,B就是右边界点。同理,③④的公共边为DE,DE在③中的逆时针顺序为,D就是左边界点,E就是右边界点。

游戏寻路之平滑路径—拉绳(漏斗)_第5张图片

  • 上图是处理多边形④到⑤的漏斗情况。
  • 根据之前的规则,公共边为FE,且F为左边界点,E为右边界点。
  • 在经过③到④后,此时的左边界为SD,右边界为SE。(漏斗算法介绍完就明白,这里③到④的结果为什么是这个了)
  • 所以此时漏斗算法,就是去比较SE,SF和旧边界SD,SE的位置关系。

此时产生两条规则:

  • SE和SE是重合的,不需要任何修改,这个很容易理解。
  • SF在SD的右侧(可以理解为外侧),同时D,F是左边界点,此时不需要更新。

游戏寻路之平滑路径—拉绳(漏斗)_第6张图片

  • 此时是⑤到⑥的漏斗处理:公共边为FG,且F为左边界点,G为右边界点。
  • 此时对比SE和SG,发现SG在SE的右侧,且已经越过了左边界SD的范围,那么说明在A星结果路径的约束下,S到G之间是不能直线联通的,此时就产生了拐角点D。

当找到拐角点之后,将拐角点加入到结果路径点集中,且以当前拐角点为起始点,重复上述过程,直到找到终点。总结规则如下:

  • 已经确定好的左右边界向量,称为“已确定左右边界向量”。
  • 算法迭代过程中,需要新对比的左右边界点所形成的向量,称为“对比左右边界”。
  • 当“对比左右边界”在“已确定左右边界”包围范围内的时候,更新“确定左右边界”为“对比左右边界”。
  • 当“对比左边界”在“已确定左边界”的右侧(外侧)。或者,“对比右边界”在“已确定右边界”的左侧(外侧)时,无需更新。
  • 当“对比左边界”在“已确定右边界”的左侧(外侧)。或者,“对比右边界”在“已确定左边界”的右侧(外侧)时,此时,产生拐角点。

终点又是一种特殊情况:

游戏寻路之平滑路径—拉绳(漏斗)_第7张图片

  • 图中END为终点,在多边形⑤内。
  • 在经历多边形④到⑤的漏斗计算后,此时的“确定左右边界”为SD,SE。

游戏寻路之平滑路径—拉绳(漏斗)_第8张图片

 

  • 如图,最终结果,D肯定是一个拐角点,因为不存在S到End之间有联通直线路径。
  • 但是,上图说明从④到⑤漏斗计算后,上下边界仍旧是SE和SD。
  • 此时,算法在多边形⑤中找到End终点的时候,会同时设定End点为新的“对边左边界点”和“对比右边界点”。即SEnd向量同时为“对比左右边界向量”
  • 按照漏斗算法流程,SEnd作为“对比右边界”时,其在“确定右边界”SE的右侧,且在“确定左边界”SD的右侧(外侧),所以D被解析为拐角点。

算法详细步骤

  • 依赖上层寻路的多边形结果集合。例如例子中的多边形①到⑨。
  • 进而得到得到①②的公共边,“左右边界点”。以当前起点为向量起点,“左右边界点”为向量终点,构造出两个“左右边界向量”。
  • 继续向下迭代,得到②③的公共边,进而得到新的“左右边界点”,仍旧以起点作为向量起点,构建两个新的“对比左右边界向量”。
  • 对比最新的两个“对比左右边界向量”和之前的两个“左右边界向量”,去更新迭代到当前多边形后确定最新的漏斗的两个边界向量。同时可能会产生拐角点。
  • 一旦出现拐角点,则将当前拐角点加入到结果路径点集中,同时以当前拐角点作为新的迭代路径起点,重复上述的过程。
  • 所有细节规则参考上述的算法详解。

算法思考

从算法的角度思考,漏斗平滑路径是完全基于上层寻路算法的,且依赖于上层寻路算法的多边形寻路结果。如下图所示:

 

游戏寻路之平滑路径—拉绳(漏斗)_第9张图片

  • 假设局部导航网格中三角形CDF也是可以直接通过的。
  • 但是上层寻路算法从S到End的寻路路径仍然是①到⑨。
  • 寻路之后的“漏斗算法”平滑依然是:SD,DG,GEnd。
  • 但是,可以直观的看出,从S到G是完全可以直线通过,而不需要拐角点D的。

造成上述问题的原因,并不是“漏斗算法”本身有问题,而正是证明了“漏斗”平滑是完全依赖于上层寻路结果的。多边形CDF可以通过,但是上层寻路的结果集中没有该多边形,所以“漏斗”也不可能去主动搜索上层寻路中没有出现的多边形。由此可见,“漏斗”平滑在广义上是有局限性的。

你可能感兴趣的:(游戏寻路)