碰撞检测 <图元测试>|基本图元测试

​ 在碰撞检测中处理相交分离需要用到一些辅助方法,例如判断两个点之间的距离有多远,点距离边有多远,点距离面有多远,两条平行线段之间有多远,两个面之间有多远,直线与直线是否相交等等测试。所以我们现在需要实现这些功能,由于我们的游戏引擎是2D的所以我们的工作量相对于3D会减少很多。

点与点之间的距离

​ 这个相信大家都会,中学的时候我们都学过两点之间的距离即欧几里得距离,公式如下:

$$ A(x_{1},y_{1}),B(x_{2},y_{2}),Distance(\overline{AB}) = \sqrt{(x_{1}-x_{2})^{2}+(y_{1}-y_{2})^{2}} $$

点与直线之间的距离

​ 点与直线之间的距离中学的时候也学了,有两种计算方式,其中一种是公式法另一种是向量法,公式法需要使用直线的直线方程不便操作,我们使用第二种方式向量法。

步骤

  1. 随便在直线上取一个向量(BC)
  2. 在BC这个向量随便选一个端点连接到点A构成向量BA
  3. 做向量BA在直线上的投影向量BD
  4. 使用BA-BD计算得向量DA
  5. 对DA取模就是点A到直线的距离了

直线与直线之间的距离(不相交)

​ 直线与直线之间的距离中学的时候也学了,有两种计算方式,其中一种是公式法另一种是向量法,公式法需要使用直线的直线方程不便操作,我们使用第二种方式向量法。

步骤

  1. 在其中一条直线上找到一个点
  2. 将问题转化为点到直线之间距离

点到AABB包围盒的最近距离

​ 这需要考虑两种情况

  1. 点在AABB包围盒外
  2. 点在AABB包围盒上/内
点在AABB包围盒外
  1. 先判断点是否在AABB外(点与矩形的相交检测)
  2. 计算点距离AABB的距离

这里有一种很奇妙的方式可以计算其距离

这里需要用到三个点P、D、B;

我们可以这么计算

float distPointAABB(FlatVector p, std::vector<FlatVector> vertices_aabb) {
    float sqDist = 0.0f;
    for (int i = 0; i < 2; i++) { 
        float v,min,max;
        if(i==0)
        {
            v = p.x ;
            min = vertices_aabb[3].x;
            max = vertices_aabb[1].x;
            /*当i为0时对应x 
            v设置为点 p 的 x 坐标。
            min 设置为边界框左上角点的 x 坐标(vertices_aabb[3].x)。
            max 设置为边界框右下角点的 x 坐标(vertices_aabb[1].x)。*/
        }
        if(i == 1) 
        {
            v = p.y;
            min = vertices_aabb[3].y;
            max = vertices_aabb[1].y;
            /*当i为1时对应y
            v设置为点 p 的 y 坐标。
            min 设置为边界框左上角点的 y 坐标(vertices_aabb[3].y)。
            max 设置为边界框右下角点的 y 坐标(vertices_aabb[1].y)。y*/
        }
        if (v < min) sqDist += (min - v) * (min - v);
        if (v > max) sqDist += (v - max) * (v - max);
    }
    return std::sqrt(sqDist); // 计算平方根
}

解释:

  • 如果 v < min,即点在边界框的左侧或下方,那么计算点到边界框左边或下边的距离 (min - v) 并将其平方累加到 sqDist
  • 如果 v > max,即点在边界框的右侧或上方,那么计算点到边界框右边或上边的距离 (v - max) 并将其平方累加到 sqDist
点在AABB包围盒上/内

​ 当点在AABB内部或者在AABB上时直接返回距离为0,且最近点为自己.

最后修改:2024 年 10 月 21 日
如果觉得我的文章对你有用,请随意赞赏