用于检查凸多面体(正方形金字塔)内的3D点的算法

时间:2016-09-28 07:26:19

标签: algorithm math 3d collision-detection polyhedra

我正在寻找强大的碰撞检测算法,并在Christer Ericson找到了一本名为实时碰撞检测的精彩书籍。我试图使用一种特定的算法来检查给定点是否在凸多面体内(在3D空间中,这些是方形金字塔,立方体和四面体(也就是所有边都是三角形的金字塔))。在我的情况下,我有一个方形金字塔。通过使用给定数量的半空间的交叉点体积并确定该点是在多面体侧面所跨越的所有平面的前面还是后面来完成点的验证。我很难理解参数n(见下文)的用法,它代表了给定多面体的半空间数:

// Test if point p inside polyhedron given as the intersection volume of n halfspaces
int TestPointPolyhedron(Point p, Plane *h, int n) {
    for (int i = 0; i < n; i++) {
        if(DistPointPlane(p, h[i]) > 0.0f) return 0;
    }
    return 1;
}

DistPointPlane(...)计算给定点和平面之间的距离

float DistPointPlane(Point q, Plane p) {
    return Dot(q, p.n) - p.d;
}

Plane是表示3D空间中的平面的结构

struct Plane {
    Vector n; // Plane normal. Point X on the plane satisfies Dot(n, X) = d
    float d;  // d = dot(n, p) for a given point on the plane
}

Plane ComputePlane(Point a, Point b, Point c) {
    Plane p;
    p.n = Normalize(Cross(b - a, c - a));
    p.d = Dot(p.n, a);
    return p;
}

算法的作用基本如下:

  1. 对于给定点,计算其到凸多面体的每个平面的距离
  2. 检查距离是负还是正
    1. 如果距离为负点位于飞机正常的另一侧,那么它就在它后面。
    2. 其他位置与飞机的正常位置相同,所以它在它前面
  3. 如果点在给定多面体的所有平面后面,它位于,否则它位于外面
  4. 现在就方形金字塔而言,据我所知有10个半空间,因为我们有4个边和一个底座,每个底座代表一个单独的平面(所以总共有5个平面)将3D空间划分为两个半空间(5 planes * 2 = 10 halfspaces)。我没有得到的是在上面算法的代码中使用n。它用作循环的终止条件,循环遍历Plane个实例的数组。但是如上所述,有10个半空间。

    在挖掘之后我想到的一件事是两个平面之间的交点是一条线(金字塔的边缘)。进一步引用Wolfram Mathworld

      

    要唯一地指定该行,还必须找到一个   特别关注它。这可以通过找到一个点来确定   同时在两个平面上

    每个金字塔的顶点都满足这个要求,因为对于任何给定的两边(包括底边),我们得到一条位于两个金字塔顶点之间的线。因此,就交叉而言,我们确实有5个(基数为4,顶点为1),但书中的文字(包括函数实现上方的注释)含糊不清,读取它可能会得到错误的想法(至少那是我的情况)。

    我的思路是接近真相还是我在数学知识方面缺少一大块?

    我已将代码移植到Python 3并将算法更改为仅通过我的平面列表循环而不需要额外的参数(如果我的想法是正确的,基本上与原始的相同)并将其绘制为matplotlib。它工作得很好但我仍然想知道我是否正确理解它:

    enter image description here

2 个答案:

答案 0 :(得分:0)

我会说你最了解它。我不确定你对“距离”究竟是什么意思。通常,dotproduct提供两个向量之间的角度。在你的情况下,有一个位置向量(点)和一个法向量。由于余弦定律,如果点积大于0,则两个矢量之间的角度小于90度。另一方面,如果产品是负的,则角度大于90度。如果它为0,则向量是正交的。所以基本上它与距离无关,而是与角度无关。

答案 1 :(得分:0)

here's a similar question

基本上你的形状是一个多面体,但它被简单地定义为通常具有许多面的形状6.您需要实际寻找名称四面体,这是您在上面的视觉表示中定义的经典金字塔形状。但基本答案是取5个平面(4个三角形和1个方形)的法线,并检查它们是否面向空间点的相同方向。如果它们都返回false,那么你的点就在形状之内。如果其中任何一个返回true,那么你就不在形状之内了。这种类型的测试适用于大多数凸形,因为没有平面与法线重叠的情况。