使用扫频AABB交叉算法解决碰撞正常问题

时间:2013-09-08 23:19:59

标签: c++ algorithm collision-detection glm-math aabb

所以我有以下扫描的AABB碰撞检测算法工作得很好和花花公子(基于this article

我的问题是如何确定碰撞正常,或换句话说,aabb0点击aabb1的方框?

我在谷歌上看起来高低无济于事。我需要正常的碰撞,所以我可以确定如何滑动'碰撞后aabb0。 (aabb0是玩家的边界框,aabb1是世界某处的静态区块。

aabb0是玩家的边界框。 d0aabb0的位移。 aabb1是世界上的一个静态块。 d1aabb1的位移(始终为0)。 u0u1是第一次和最后一次碰撞时间。

template<typename T>
intersect_type_t intersects(const aabb_t<T> aabb0, const T& d0, const aabb_t<T>& aabb1, const T& d1, float32_t& u0, float32_t& u1)
{
    auto v = glm::value_ptr((d1 - d0));
    auto amin = glm::value_ptr(aabb0.min);
    auto amax = glm::value_ptr(aabb0.max);
    auto bmin = glm::value_ptr(aabb1.min);
    auto bmax = glm::value_ptr(aabb1.max);
    vec3_t u_0(FLT_MAX);
    vec3_t u_1(FLT_MIN);

    if(intersects(aabb0, aabb1) != intersect_type_t::disjoint)
    {
        u0 = u1 = 0;
        return intersect_type_t::intersect;
    }

    for(size_t i=0; i < 3; ++i)
    {
        if(v[i] == 0)
        {
            u_0[i] = 0;
            u_1[i] = 1;
            continue;
        }

        if(amax[i] < bmin[i] && v[i] < 0)
            u_0[i] = (amax[i] - bmin[i]) / v[i];

        else if(bmax[i] < amin[i] && v[i] > 0)
            u_0[i] = (amin[i] - bmax[i]) / v[i];

        if(bmax[i] > amin[i] && v[i] < 0)
            u_1[i] = (amin[i] - bmax[i]) / v[i];

        else if(amax[i] > bmin[i] && v[i] > 0)
            u_1[i] = (amax[i] - bmin[i]) / v[i];
    }

    u0 = glm::compMax(u_0);
    u1 = glm::compMin(u_1);

    return u0 >= 0 && u1 <= 1 && u0 <= u1 ? intersect_type_t::intersect : intersect_type_t::disjoint;
}

1 个答案:

答案 0 :(得分:2)

用以下代码替换了我的返回函数:

auto result = u0 >= 0 && u1 <= 1 && u0 <= u1 ? intersect_type_t::intersect : intersect_type_t::disjoint;

if(normal != nullptr && result == intersect_type_t::intersect)
{
    auto normal_value_ptr = glm::value_ptr(*normal);
    for(size_t i = 0; i < 3; ++i)
    {
        if(u_0[i] == u0)
        {
            normal_value_ptr[i] = v[i] > 0 ? 1.f : -1.f;
            break;
        }
    }
}

return result;