我有两个正在移动的AABB,检查它们是否在框架下相交的最快方法是什么?
通过移动,我的意思是不仅要检查常用的矩形交集方法,还意味着某种简单易行的测试,该测试仅返回布尔值,没有命中时间或其他任何东西。
我认为就是这样简单地做到这一点:
但是那个Hexagon非常复杂,我不知道如何计算AABB-多边形相交,也许有更简单的方法吗?
您最喜欢的任何编程语言,我都可以轻松移植。
谢谢。
我有两个正在移动的AABB,检查它们是否在框架下相交的最快方法是什么?
通过移动,我的意思是不仅要检查常用的矩形交集方法,还意味着某种简单易行的测试,该测试仅返回布尔值,没有命中时间或其他任何东西。
我认为就是这样简单地做到这一点:
但是那个Hexagon非常复杂,我不知道如何计算AABB-多边形相交,也许有更简单的方法吗?
您最喜欢的任何编程语言,我都可以轻松移植。
谢谢。
Answers:
使用Minkowski总和
解决此问题的一个好方法是考虑转换为原点(v')的运动线(v)与原点(A')旋转180度的A的Minkowski和与障碍物之间的交点(仅B在这种情况下):A” ⊕ 乙。
在下图中,我在任意坐标系的原点中放置了一个 smack-dab。这简化了理解,因为将A旋转180度会导致A',并且将v转换为原点等于v'。
Minkowski和是绿色矩形,通过进行线-AABB交点可以找到运动的A和静止的B的交点。这些点用蓝色圆圈标记。
在下图中,使用了不同的原点,并且找到了相同的交点。
多个移动AABB
为了使这项工作了两个的AABB期间的特定时间段,你会减去以线性方式移动乙 “从s的速度矢量甲 S波速度矢量和使用”,作为线段的线AABB相交。
伪代码
def normalize(aabb):
return {x1: min(aabb.x1, aabb.x2), x2: max(aabb.x1, aabb.x2),
y1: min(aabb.y1, aabb.y2), y2: max(aabb.y1, aabb.y2),
def rotate_about_origin(aabb):
return normalize({x1: -aabb.x1, x2: -aabb.x2
y1: -aabb.y1, y2: -aabb.y2})
# given normalized aabb's
def minkowski_sum(aabb1, aabb2):
return {x1: aabb1.x1+aabb2.x1, x2: aabb1.x2+aabb2.x2,
y1: aabb1.y1+aabb2.y1, y2: aabb1.y2+aabb2.y2}
def get_line_segment_from_origin(v):
return {x1: 0, y1: 0, x2: v.x, y2: v.y}
def moving_objects_with_aabb_intersection(object1, object2):
A = object1.get_aabb()
B = object2.get_aabb()
# get A'⊕B
rotated_A = rotate_about_origin(A)
sum_aabb = minkowski_sum(rotated_A, B)
# get v'
total_relative_velocity = vector_subtract(object1.get_relative_velocity(), object2.get_relative_velocity())
line_segment = get_line_segment_from_origin(total_relative_velocity)
# call your favorite line clipping algorithm
return line_aabb_intersection(line_segment, sum_aabb)
碰撞反应
根据游戏玩法,您将执行更细粒度的碰撞检测(可能是AABB的网格物体),或者前进到下一阶段:碰撞响应。
发生碰撞时,线A-ABB交点算法将分别返回1或2个交点,这取决于A是在B内结束运动还是通过B。(这是对A沿其边或沿其各个角之一吃草B的退化案例的打折。)
无论哪种方式,沿线段的第一个交点都是碰撞点,您都可以将其转换回世界坐标系中的正确位置(第二幅图片中第一个浅蓝色圆圈沿原始v,称为p),然后确定(例如,对于弹性碰撞,通过沿p处的碰撞法线反射v),在帧末尾A的实际位置将是(At + 1)。
如果有两个以上的对撞机,这将变得稍微复杂一些,因为您也想对v的第二个反射部分进行碰撞检测。
您首先需要将运动分解为较小的步骤,然后使用该信息来计算高级AABB。如果较大的AABB相交,则可以检查较小的步长以使其更准确。
如果任一对象快速旋转并且在一个维度上比另一个维度更长,则仅通过使用起始和结束位置来检查ABB(或OOBB)来估计是否存在碰撞可能会错过碰撞。
要计算更准确的估算AABB,将运动分解为较小的步长,然后仅使用初始AABB(而不是对象网格),旋转AABB(现在只是一个框,没有轴对齐),因为对象将在每个位置旋转和移动步。每个轴的最大和最小点将为您提供包围对象整个运动的AABB。
如果与较大的ABB交叉,则可以使用已经计算出的较小的ABB,以确定可能发生碰撞的位置。对于与另一个对象相交的每个较小的AABB,您可以执行更昂贵的网格相交检测。
您将不得不将运动分解为较小的运动步骤。例如:
您想使用更大的分量(在本例中为X轴)分解运动,然后在每个步骤中检查碰撞。
这看起来可能太昂贵了,但是要考虑到一个对象在每个循环中移动得快于其自身宽度的速度将非常快,因此这种情况并不像您首先想到的那样普遍。
您还应该使用相对速度进行碰撞检查,以使一个AABB为“静态”,而另一个以其自身速度减去“静态”一个的速度运动。
最快的方式,看看他们是否可以相交是刚刚拓展移动AABB的速度。
例如,AABB以0.1 x /帧向右移动,然后将其扩展,以使左边缘保持不变,而右边缘则进一步保持0.1。然后,您可以检查新的AABB。如果为假,则不存在冲突。(提早返回并在小速度时准确)。
然后,您可以检查运动对象的末端和起点AABB是否相交。如果为true,则返回true。
否则,您需要检查对角线是否与静态ABB相交。
这涉及获取对角线的坐标,其中x =静态元素的左边缘,右边缘查看y是否在底部和顶部之内。(反过来重复)