OBB与OBB碰撞检测


20

假设您有两个边界框对象,每个边界框对象都将框的当前顶点存储在矢量中,并且该对象的所有顶点都相对于公共轴旋转和平移。

这是一张图像来说明我的问题:

如果两个OBB重叠任何链接以帮助解释该问题的解决方案,我将如何解决?请不要太费解了...

Answers:


16

OBB是凸包。凸包是3D形状,在其表面上没有“碎屑”。凸包上的每个“凸点”(顶点)都向外突出,从不向内突出。如果通过凸包对平面进行切片,则将获得(只有一个)凸多边形。如果您在凸形船体内部并向外部发射激光,则只能穿透船体表面一次(永远不会两次)。

分离轴定理测试可用于检测凸包的碰撞。SAT测试很简单。它适用于2D和3D。尽管下面的图片为2D,但它们也可以轻松应用于3D。

概念

这是您在SAT中使用的关键概念:

  • 当两个形状“投影”到两个形状的每个法线轴上时,只有重叠时才相交。

形状在1D向量上的“投影”看起来像这样(我称之为“挤压”)

具有红色顶点和轴的形状

在此处输入图片说明

“将形状投影到轴上”是指从形状上的每个点垂直放置一个垂线以使其刚好落在轴上。您可以认为这是用一只手“压碎”了点,将所有东西收集起来并垂直将其压碎到轴。

在此处输入图片说明

剩下的是:轴上的点

在此处输入图片说明

SAT说:

要使2个凸包相交,它们必须在每个轴上重叠(其中,必须检查任一形状上的每个法线都作为一个轴)。

采取以下两种形状:

在此处输入图片说明

您会看到它们没有相交,因此让我们尝试几个轴以显示没有发生重叠。

尝试五边形的最高法线:

在此处输入图片说明

这些是范围。它们确实重叠。

在此处输入图片说明

尝试矩形的左侧。现在它们在该轴上不重叠,因此没有相交。

在此处输入图片说明

算法:

对于两种形状上的每个面法线

  • 找到两个形状的所有顶点角点在该轴上的投影的最小和最大范围(最大和最小值)
  • 如果它们不重叠,则没有交集

就是这样。使SAT工作的代码非常简短。

这是一些代码,演示如何进行SAT轴投影:

void SATtest( const Vector3f& axis, const vector<Vector3f>& ptSet, float& minAlong, float& maxAlong )
{
  minAlong=HUGE, maxAlong=-HUGE;
  for( int i = 0 ; i < ptSet.size() ; i++ )
  {
    // just dot it to get the min/max along this axis.
    float dotVal = ptSet[i].dot( axis ) ;
    if( dotVal < minAlong )  minAlong=dotVal;
    if( dotVal > maxAlong )  maxAlong=dotVal;
  }
}

调用代码:

// Shape1 and Shape2 must be CONVEX HULLS
bool intersects( Shape shape1, Shape shape2 )
{
  // Get the normals for one of the shapes,
  for( int i = 0 ; i < shape1.normals.size() ; i++ )
  {
    float shape1Min, shape1Max, shape2Min, shape2Max ;
    SATtest( normals[i], shape1.corners, shape1Min, shape1Max ) ;
    SATtest( normals[i], shape2.corners, shape2Min, shape2Max ) ;
    if( !overlaps( shape1Min, shape1Max, shape2Min, shape2Max ) )
    {
      return 0 ; // NO INTERSECTION
    }

    // otherwise, go on with the next test
  }

  // TEST SHAPE2.normals as well

  // if overlap occurred in ALL AXES, then they do intersect
  return 1 ;
}

bool overlaps( float min1, float max1, float min2, float max2 )
{
  return isBetweenOrdered( min2, min1, max1 ) || isBetweenOrdered( min1, min2, max2 ) ;
}

inline bool isBetweenOrdered( float val, float lowerBound, float upperBound ) {
  return lowerBound <= val && val <= upperBound ;
}

Hullinator对凸包实施SAT测试
bobobobo

很棒的解释!谢谢。我认为您可能在一行中有一个错别字:“因此,让我们尝试几个轴来显示没有发生重叠。”,因为然后您将继续举例说明它们确实重叠。再次感谢!

您是否还需要对所有法线​​的叉积进行测试?这篇文章geometrictools.com/Documentation/DynamicCollisionDetection.pdf是这样说的。
iNFINITEi

值得指出的是,这种特定的SAT方法仅适用于2D。在3D中,您不仅需要获得每张脸的法线,还需要获得更多。但是,一旦有了正确的法线,其余过程(项目,比较)便完全相同。
基金莫妮卡的诉讼

从2D图片中很难分辨出箭头的方向。
WDUK

7

您绝对应该查找“ 分离轴定理”。它用于凸物体。有一条规则:“如果两个凸对象不相交,则存在一个平面,这两个对象的投影将不相交”。

您可以在Wiki上找到一些示例。但这比您的情况要复杂一些。

这里可以找到更适合您的问题的东西(两辆汽车相撞)。


1

更多SAT文章。

该网站上的最后一篇文章带有完整的代码,我认为它是在FLASH中,我不知道,但是当我第一次使用SAT时,将它转换为C ++时我遇到了0个问题,应该不难其他语言也一样。您唯一需要添加的就是在每次计算中存储位移向量(如果是最小的话,当然,当您了解SAT时您会明白这一点),本教程中的代码不会这样做,因此您最终得到的是最后计算出的向量。

http://rocketmandevelopment.com/tag/separation-axis-theorem/

不错的旧版N-Game教程。网络上最好的SAT理论。

http://www.metanetsoftware.com/technique/tutorialA.html


如此令人讨厌的是,没有人发布所有必需类的完整工作资料。我将他的代码移植到了自己的演示中,但是那是行不通的。:(这是我的项目,到目前为止,如果有人可以帮助我调试它,那将是巨大的。 链接
约书亚巴尼特

您什么意思不起作用?注意您如何存储顶点,在图像中将它们放置在笛卡尔坐标系中,在本教程中,他将顶点存储为相对于质心的矢量(您要做的就是从您自己的顶点中减去质心,或者删除他修改自己顶点的线条),可以创建自己的点积之类的功能,不需要这些指南,其余的应该简单明了,而不是复制粘贴材料,在尝试实施之前学习SAT
dreta 2012年

这就是我的实现方式:SAT.asShape2D.as,质心是什么意思?多边形的中心,例如(x,y)?
Joshua Barnett 2012年

目前,我有一个函数getOBB(),它返回原始图像中详细说明的顶点。这是通过Vector <b2Vec2>计算的,该向量包含形状的顶点,角度变量和位置变量。
Joshua Barnett 2012年

是的,中心,这个人创建多边形的方式是通过给中心idk AS3给出偏移量,但是从我的角度来看,您投影顶点时是这样的,在计算点积时,请尝试从这些顶点减去质心(向量相减),
除此之外
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.