Cube on Cube碰撞检测算法?

时间:2010-09-02 21:28:17

标签: algorithm language-agnostic

我正在尝试找到最有效的方法来检查2个任意大小的立方体是否相互碰撞。立方体的侧面长度不一定都是相同的(盒子是可能的)。鉴于这些限制,我怎样才能有效地检查它们是否发生碰撞? (每个方框有24个顶点)谢谢

它们是轴对齐

2 个答案:

答案 0 :(得分:14)

由于两个方框都是轴对齐的,因此您只需比较它们的范围:

  return (a.max_x() >= b.min_x() and a.min_x() <= b.max_x())
     and (a.max_y() >= b.min_y() and a.min_y() <= b.max_y())
     and (a.max_z() >= b.min_z() and a.min_z() <= b.max_z())

答案 1 :(得分:1)

对于布尔查询,请使用Laurence的答案。它也可以用于移动框,但是你必须使用二分搜索来找到交叉点或时间间隔。

求解轴上交点的参数时间

如果你想要可移动的盒子,另一个解决方案是找到相对于行进方向分别在每个轴上发生交叉的参数时间。我们将方框A和B称为Min和Max的极值点。你只需要一个方向,因为你可以从B的方向中减去A的方向,并留下一个向量。所以你可以认为B是移动而A是静止的。让我们称之为方向D.求解t给出:

(对于沿D的交叉点的开始)
Bmax + t输入 D = Amin
输入
D = Amin - Bmax
tEnter =(Amin-Bmax)/ D

(沿D的交叉点的末端; A的背面)
Bmin + tLeave D = Amax
tLeave
D = Amax - Bmin
tLeave =(Amax - Bmin)/ D

对每个轴进行检查,如果它们全部重叠,则会有一个交叉点。如果分母为零,则该轴上存在无限重叠或无重叠。如果tEnter大于1或tLeave小于零,则重叠距离方向长度或方向错误。

bool IntersectAxis(float min1, float max1, float min2, float max2,
    float diraxis, float& tEnter, float& tLeave)
{
    const float intrEps = 1e-9;

    /* Carefully check for diraxis==0 using an epsilon. */
    if( std::fabs(diraxis) < intrEps ){
        if((min1 >= max2) || (max1 <= min2)){
            /* No movement in the axis, and they don't overlap,
                hence no intersection. */
            return false;
        } else {
            /* Stationary in the axis, with overlap at t=0 to t=1 */
            return true;
        }
    } else {
        float start = (min1 - max2) / diraxis;
        float leave = (max1 - min2) / diraxis;

        /* Swap to make sure our intervals are correct */
        if(start > leave)
            std::swap(start,leave);

        if(start > tEnter)
            tEnter = start;
        if(leave < tLeave)
            tLeave = leave; 
        if(tEnter > tLeave)
            return false;
    }
    return true;
}

bool Intersect(const AABB& b1, const AABB& b2, Vector3 dir, float& tEnter, float&         tLeave)
{
    tEnter = 0.0f;
    tLeave = 1.0f;

    if(IntersectAxis(b1.bmin.x, b1.bmax.x, b2.bmin.x, b2.bmax.x, dir.x, tEnter, tLeave) == false)
        return false;
    else if(IntersectAxis(b1.bmin.y, b1.bmax.y, b2.bmin.y, b2.bmax.y, dir.y, tEnter, tLeave) == false)
        return false;
    else if(IntersectAxis(b1.bmin.z, b1.bmax.z, b2.bmin.z, b2.bmax.z, dir.z, tEnter, tLeave) == false)
        return false;
    else
    return true;
}