点、线段、凹多边形相交判断以及游戏中的常见应用

本文接前文点、线段、多边形相交判断以及在游戏中常见的物理应用
前文主要讲解点、线段、凸包之间的相交判断算法,本文主要解释凹多边形(简称凹包)的判断方法。

一、简单多边形

由于以下论述都是基于简单多边形,因此线解释什么是简单多边形,如下左图是简单多边形,右图则不是。

也就是自身无交叉的属于简单多边形,而带有交叉的就不属于简单多边形。
左侧是一个典型的凹包。

二、如何判断顶点与凹包是否相交

这里先提出一个简单的方法,也是比较快速的方法,如果我们只是需要知道顶点与某个凹包是否相交的话,就可以使用射线法:

如上图,假设需要判断M与凹包关系,则可以从M点向右发射射线,查看击中凹包边缘的次数(就是使用前文所述的夹持法来判断交叉,附带+X轴向判断条件),如果击中的次数为奇数,则表示M位于凹包内部,如果为偶数,则处于外部。
该方法简单移动,也比较快速,甚至可以超越凹包判断带有自身交叠的凹多边形。

三、如何判断线段与凹包相交

可能你最直接想到的就是:如果一个顶点位于凹包内部,另外一个顶点位于凹包外部,则可以认为相交,这样大致是正确的,但是它未能处理穿透的情况,如下图:

这里我先提出一个与问题二很类似的解决方法,就是判断凹包中所有线段与目标线段MN的交叉次数,如果交叉次数为奇数,则表示MN与凹包相交且一个顶点位于凹包内部,如果为偶数,则认为相交且穿透,如果为0,则认为是不相交,或者线段MN包含在凹包内部。
尽管这个方法也很快,仍然保持了可以适用于带有自身交叠的凹多边形,然而其也有不足,就是无法区分出是不相交,还是包含在凹包内部,需要借助问题而来辅助解决最终的判断。

四、如何判断凸包与凹包的相交

由于通常来说,凹包计算都很消耗性能(回忆上文的凸包判断中的排他性),所以在游戏引擎中,一般可以运动的刚体,所能携带的动态碰撞体都不能使用凹包。然而,携带凸包碰撞体的刚体,在运动时仍然可以快速碰撞崎岖不平的地面(地形是一个凹包,静态碰撞体),这是因为,二者的快速碰撞,使用的凹包中的顶点与刚体碰撞体凸包进行快速排斥运算,因此仍然能够得到不错的性能。
也就是说,判断凹包与凸包是否相交的简单方法,就是遍历凹包所有顶点,只要有一个顶点在凸包内部,也就发生了碰撞(相交),相反,如果一个顶点也不在凸包内部,此时,可能是没有碰撞,也可能是凹包完全包含了凸包。可以看出,这个简单的方法并不严密,效率也不高,因为针对每个凹包顶点都需要逐一遍历,以凹包顶点数乘以凸包顶点数的计算复杂度才能完成。
更高效严密的算法,见后续文章。

五、游戏中的凹包与凸包应用

在游戏中,最常见的凸包应用就是动态碰撞体,凹包应用就是静态碰撞体,一般而言,当碰撞体产生交叉时,物理引擎就会将可运动的碰撞体弹开,而每次接近运动时,只需要判断运动方向上,可能侵入凸包范围内的那些顶点,因此刚体凸包与非常复杂的静态碰撞体凹包之间的相互计算也非常快。
然而,在某些情况下,刚体不允许被弹开,比如在Unity中将某个静态碰撞体设置为Trigger,作为触发区域,它本身不做碰撞反应,然而却需要做碰撞检测,在这种情况下,性能开销相对于非Trigger状态开销要大得多,因为整个Trigger都允许侵入刚体,所以作为Trigger,首先需要使用凸包,IsConvex要首先开启,才可以IsTrigger,即便都是用凸包,仍然非常消耗性能。所以应该尽可能精简Trigger碰撞体的顶点数。

六、凹包与凹包的相交计算

见后续文章“扫线法快速判断凹多边形相交”

发布了66 篇原创文章 · 获赞 158 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/AndrewFan/article/details/103882596