【问题标题】:Cube on Cube collision detection algorithm?Cube on Cube 碰撞检测算法?
【发布时间】:2010-09-02 21:28:17
【问题描述】:

我正在尝试寻找最有效的方法来检查 2 个任意大小的立方体是否相互碰撞。立方体的边不一定都等长(可以是一个盒子)。鉴于这些限制,我如何有效地检查它们是否发生碰撞? (每个盒子有 24 个顶点)谢谢

它们是轴对齐的

【问题讨论】:

  • 碰撞空间是二维的还是三维的?如果您不介意碰撞不精确,您可以通过使用距立方体中心的任意距离作为外边界来估计立方体的边界。
  • 这会导致球形或非盒子碰撞检测吗?
  • 什么样的盒子有24个顶点?一个立方体(或任何矩形棱柱,就此而言)有 8 个顶点。
  • 因为我没有使用索引所以有重叠,我很快就会解决这个问题,
  • 另外,这些框是轴对齐的吗?

标签: algorithm language-agnostic


【解决方案1】:

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

  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())

【讨论】:

  • Min 和 Max 真的会找到最小值和最大值吗,就这么简单吗?例如,遍历所有顶点,如果 v.x
  • 是的,但如果只有 b 轴对齐,您只需要进行迭代。由于两者都是轴对齐的,因此更加简单。请参阅我刚刚添加的最后一点。
  • 投反对票。这对于碰撞检测不是很有帮助。这是一个布尔查询。它没有找到交点,也没有与移动的物体一起工作。这种方法只适用于非常特殊的情况。
  • @Mads:问题中指定了它工作的“特殊情况”。
  • 它也不适用于三角形。或渲染 4 维网格。或者给我的爆米花涂黄油。嘘。
【解决方案2】:

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

求解轴上相交的参数化时间

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

(用于沿 D 的交叉点的起点)
Bmax + tEnterD = Amin
tEnter
D = Amin - Bmax
tEnter = (Amin - Bmax) / D

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

在每个轴上执行此检查,如果它们都重叠,则您有一个交叉点。如果分母为零,则该轴上有无限重叠或没有重叠。如果 tEnter 大于 1 或 tLeave 小于 0,则重叠比方向长度更远,或者方向错误。

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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多