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

本文记录一些常见的相交判断方法,属于游戏开发中比较常见的几何应用。

目录

一、线段之间的相交判断:

二、顶点走向判断

三、路径导航

四、顶点与凸包相交计算

五、线段与凸包的相交计算

六、凸包与凸包的相交判断


一、线段之间的相交判断:

问题,如下图,如何判断线段AB和CD是否相交?


解答:线段之间的相交判断一般使用以下夹持法思路:
1、假如ABC保持现有位置,D可移动,那么穿透交叉的条件就是D在AB的另外一侧(异于C),且CD夹持于射线CA、CB之间
2、假如ACD保持现有位置,B可移动,那么穿透交叉的条件就是B在CD的另外一侧(异于A),且AB夹持于射线AD、AC之间
总结1、2,可以说成:
A、B两点分布于直线CD的两侧,C、D点分布于直线AB的两侧,形成互相夹持。
理清思路再去找相应的公式:
由于2D矢量的叉积是一个标量,上述1、2的夹持条件,可以由以下简单的叉积公式来体现:


Vcd.Cross(Vca) * Vcd.Cross(Vcb) < 0  && Vab.Cross(Vad) * Vab.Cross(Vac) < 0 

这里的<也可以是<=,那么将代表可以包含穿过顶点的临界情况。

二、顶点走向判断

在带有物理计算的游戏中,常常需要进行物体走向的判断,这个说起来也很简单,给出问题如下:
如下图,假设AB朝向代表了人物当前的朝向,人物处于顶点A位置,而此时希望A转向M,那么A该如何最快转向至面向M?

解答:依然使用问题一种的叉积,如若Vab.Cross(Vam) > 0 则说明 M在当前朝向的顺时针方向(左手系),此时应该顺时针旋转,反则反之。

三、路径导航

在游戏中,我们常常需要路径导航,如在Unity中,由NaviMesh等相关组件可以生成一系列的导航点,很多时候系统组件的导航功能不能满足我们的需要,此时我们需要自己执行导航计算。
也就是说,提出问题,如下图,当前有路径点(Way Point)A、B、C、D、E,假设移动对象从A点出发,该如何导航使其顺利抵达E点?

解答:这个问题实际上可以基于问题一、二中的思路。
1、首先假设针对每个路径点都作垂线,如上图所示,那么我们的空间将被这些垂线划分。有的划分出现交叠,不过这不要紧,稍后会做解释。
2、接着我们考虑每个顶点所划分的区域,左下角到A点垂线的区域属于A,A点垂线到B点垂线的区域属于B...
3、移动对象同时只允许出现在一个区域内,比如刚开始处于A区域
4、一旦越过路径点垂线,即进入下一个区域,且不允许回头
5、在任意一个区域内,移动对象都是向着当前路径点方向移动,移动方向被夹持在路径朝向和垂线方向之间
基于以上规则,可以使用一些基础的几何运算就可以完成相对完善的导航逻辑。

四、顶点与凸包相交计算

问题:如下图所示,如何判断点M是否位于凸包ABCDEF内部?

解答:凸包与顶点之间的相交判断相对来说很快,算法也相对容易。有两种算法:
一种是GJK算法,见我的文章GJK 算法,另外一种更简单一些,就是使用问题二中的走向判断思路:
1、从A点出发,经B一直到F,沿途一直判断M与所经过的线段的侧向关系。
2、假设任意一次侧向判断中,M出现在右侧,则算法结束,结果是不包含,因为只要出现在任意一条线段的外侧,该顶点就不会被包含在凸包中,这种排他性也是凸包计算快的重要原因。
3、假设直到路径结束,一直没有出现在右侧,则说明包含在内部。
读到这里你可以有一个问题,如果这条路径很长,而顶点确实在其中,那么岂不是都需要走完整条路径才能完成判断,在这里的但是是这样的,那么有没有更好的办法。然而如果你读过GJK 算法,就可以知道,通过拟合不同方向的单纯形,可以在空间上跨越判断,而不是一步步计算每一条线段。

五、线段与凸包的相交计算

问题:如下图所示,如何判断线段MN是否与凸包ABCDEF相交?需要判断出交叉和包含的情况。


解答:这里的解答实际上仍然可以使用GJK 算法完成,然而对于常见的简单情况,我们更容易想到的就是:
如果任意一条凸包线段与MN线段相交,结果就是相交,因此,这里结合使用以上问题的思路,可以完成解答。
这里特殊要说明的是,不能仅仅通过判断一个顶点在内部,另外一个顶点在外部来判断相交结果,因为对于穿透的情况,如N在CD的外侧,如下图:

此时两个顶点都处于外部,然而仍然是发生的相交。另外也需要考虑两个顶点均处于凸包内部而没有线段交叉的情况。
 

六、凸包与凸包的相交判断

凸包与凸包之间的相交可以使用分离轴定理或者GJK 算法完成。
多边形判断的难点在于凹多边形,后续文章将给出一些常见算法。

展开阅读全文
©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值