微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

比较所有碰撞盒的最有效方法?

如何解决比较所有碰撞盒的最有效方法?

我正在尝试为我的游戏想出一个碰撞算法,但在实现它的方法上很挣扎。我有一个碰撞盒对象,它包含所有相关的碰撞数据,然后在我的游戏对象中有一个 CollisionBox* 向量来处理每个碰撞器。

但是我的方法需要为每次碰撞调用相同的函数 4 次,并且嵌套循环保证在循环完成之前将多次检查相同的碰撞,并且每帧都调用它,因此性能会很差.这是我写的

void Game::CheckCollisions() {
  vector<CollisionBox*>::iterator it;
  for (it = colBoxes.begin(); it != colBoxes.end(); ++it) {
    //for each Box - compare the 4 corner points with every other Box,only compare different collision layers
    Vector3 BoxPos = (*it)->mModel.GetPosition();
    for (vector<CollisionBox*>::iterator it_2 = colBoxes.begin(); it_2 != colBoxes.end(); ++it_2) {
      if ((*it) != (*it_2) && (*it)->colLayer != (*it_2)->colLayer && (*it)->isActive && (*it_2)->isActive) {   
        IsPointInside((*it)->tl,*(*it_2)); //tl  
        IsPointInside((*it)->tr,*(*it_2)); //tr
        IsPointInside((*it)->bl,*(*it_2)); //bl
        IsPointInside((*it)->br,*(*it_2)); //br    
      }
    } 
  }
}

bool Game::IsPointInside(const DirectX::SimpleMath::Vector3& point,CollisionBox& Box) {
  return (point.x >= Box.bl.x && point.x <= Box.tl.x) &&      
    (point.y >= Box.bl.y && point.y <= Box.tl.y);           
}

解决方法

有很多方法可以改进此代码的性能。

首先,最好以连续的方式将碰撞数据放在一起。您的向量应包含测试碰撞所需的最小值。如果有帮助,您可以使用 SOA instead of AOS

那么你的碰撞算法是不正确的。您不是在检查形状是否重叠,而是在形状内部有一个顶点。这不包括此类冲突:

        o----o
   o----|    |---o
   |    |    |   |
   o----|    |---o
        o----o

如您所见,另一个多边形内没有顶点,但肯定会发生碰撞。

此外,您的数据是不正确的,因为它包含的数据比需要的多得多。要在内存中表示一个对齐框,你只需要两个向量:

Top left
   o--------|
   |        |
   |        |
   |--------o Bottom right

然后实现 AABB 碰撞(在 2D 或 3D 中)变得非常简单。

auto aabb_intersect(CollisionBox const& a,CollisionBox const& b) noexcept -> bool {
    return (
        (a.tl.x <= b.br.x && a.br.x >= b.tl.x) &&
        (a.tl.y <= b.br.y && a.br.y >= b.tl.y) &&
        (a.tl.z <= b.br.z && a.br.z >= b.tl.z)
    );
}

为了进一步提升性能,您需要其他方法,例如空间哈希分区、四叉树/八叉树或其他方法。

如果您想要性能,请始终衡量并确定瓶颈。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。