2013-09-08 5 views
3

Так что у меня следующий прокатилась ААББ алгоритм обнаружения столкновений работает все хорошо и денди (на основе this article)Разрешающая столкновения нормального использования прокатилась алгоритм пересечения AABB

Мой вопрос, как я могу определить коллизию нормально, или другими словами, сторона коробки, которую aabb0 ударил aabb1?

Я смотрел высоко и низко на Google безрезультатно. Мне нужно нормальное столкновение, поэтому я могу определить, как «сползать» aabb0 после столкновения. (aabb0 является ограничивающим полем игрока, а aabb1 является статическим блоком где-то в мире).

aabb0 является ограничивающим полем игрока. d0 - смещение aabb0. aabb1 - это статический блок в мире. d1 - смещение aabb1 (всегда 0). u0 и u1 - первое и последнее время столкновения.

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

ответ

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;