目 录CONTENT

文章目录

碰撞检测

hananww
2026-06-05 / 0 评论 / 0 点赞 / 2 阅读 / 0 字
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

碰撞检测(基础)

🔴 球体碰撞 (Circle / Sphere)

这是最简单、计算成本最低的碰撞检测,常用于子弹、粒子、或者近似圆形的角色(如2 D游戏中的吃豆人、3 D游戏中的滚动球)。

1. 需要哪些数据?

要描述一个圆(2D)或球体(3D),只需要两个核心数据:

  • 中心点 (Center):一个二维向量 (x,y) 或三维向量 (x,y,z) ,表示圆心在世界坐标系中的位置。
  • 半径 (Radius):一个标量(单一数值) rr ,表示中心到边缘的距离。

2. 数学原理

判断两个圆(A和B)是否碰撞,核心逻辑极其直观:如果两个圆心的距离,小于或等于它们的半径之和,则发生碰撞。

  • 计算距离:利用向量减法得到从 A 指向 B 的方向向量 ​\vec{D} = Center_B - Center_A
  • 计算长度:利用勾股定理(毕达哥拉斯定理)计算该向量的模长(即两点间的直线距离):​d = \sqrt{D_x^2 + D_y^2}
  • 判定条件:如果 ​d \le r_A + r_B ,则碰撞。

💡 核心优化思维(平方比较法): 在计算机中,开平方根(​\sqrt{})是非常耗时的运算**。因为等式两边都是正数,我们可以直接将两边平方,把判定条件改为: ​D_x^2 + D_y^2 \le (r_A + r_B)^2 这样全程只需要乘法和加法,极大地提升了性能。

3. 用到的数学知识

  • 向量代数:向量的减法(求相对位置)。
  • 解析几何:欧几里得距离公式(勾股定理在坐标系中的应用)。
  • 不等式变换:利用单调递增函数的性质,将开方运算转化为平方运算。

🔴 轴对齐包围盒碰撞 (AABB vs AABB)

AABB (Axis-Aligned Bounding Box) 是指边永远平行于坐标轴(X/Y/Z轴)的矩形或长方体。它不能旋转,一旦物体旋转,AABB 就必须重新计算扩大。它是游戏引擎中最常用的粗略碰撞体(如墙壁、地板、静态道具)。

1. 需要哪些数据?

描述一个 AABB 通常有两种数据表示法(数学上等价):

  • 极值表示法
    • 2 d 空间记录矩形在坐标系中的最小点 ​(minX, minY)最大点 ​(maxX, maxY)
    • 3 D 空间记录这个长方体在三维世界中,最靠近原点的那个角(最小点),和最远离原点的那个对角(最大点)
      • 最小点 ​P_{min}:(x_{min},y_{min},z_{min})
      • 最大点 ​P_{max}:(x_{max},y_{max},z_{max})
  • 中心 + 半尺寸表示法(引擎更常用)
    • 2 d 空间记录中心点 ​(cx, cy)半宽/半高 ​(hw, hh)
    • 记录长方体的几何中心,以及它在 X、Y、Z 三个方向上“厚度”的一半。
      • 中心点 ​ C:(c_{x},c_{y},c_{z})
      • 半尺寸 ​ H:(h_{x},h_{y},h_{z}) (即半宽、半高、半深)

2. 数学原理(2 D)

AABB 碰撞检测的数学本质是一维区间的重叠判定

AABB 碰撞检测的数学本质是一维区间的重叠判定。 在二维空间中,两个矩形碰撞的充要条件是:它们在 X 轴上的投影区间重叠,并且在 Y 轴上的投影区间也重叠。只要有一个轴存在缝隙,就不碰撞。

  • 如果用“极值表示法”(区间交集原理):

    • X轴重叠:​A.maxX \ge B.minX​A.minX \le B.maxX
    • Y轴重叠:​A.maxX \ge B.minX​A.minX \le B.maxX
    • 两者同时满足即碰撞。
  • 计算两个中心点在 X 轴上的绝对距离:​|cx_A - cx_B|

  • 计算两个矩形在 X 轴上的“安全半径之和”:​hw_A + hw_B

  • X轴重叠条件:​|cx_A - cx_B| \le hw_A + hw_B

  • Y轴同理。两者同时满足即碰撞。

3. 用到的数学知识(2 D)

  • 区间数学 (Interval Arithmetic):一维线段的重叠与交集判定。
  • 绝对值与不等式:利用绝对值表示无方向的距离。
  • 降维思想:将复杂的二维面积重叠问题,拆解为两个独立的一维线段重叠问题(这在数学上称为正交分解)。

3D 空间实战推演(具体例子)

要判断两个 3D 长方体是否相交,最笨的办法是算体积,但这在数学上极其复杂。
这里用到的核心数学思想是:正交分解(降维)

原理:两个 3D 长方体发生碰撞的充要条件是:它们在 X 轴、Y 轴、Z 轴上的投影(也就是 3 条一维线段)同时发生重叠

反证法:只要它们在任意一个轴(比如 Z 轴)上的投影存在缝隙(不重叠),那么这两个长方体在 3D 空间中就绝对不可能碰到对方

这就把复杂的“3D 体积相交”问题,拆解成了 3 个极其简单的“1D 线段重叠”问题

假设我们在开发一个 3D 动作游戏。

  • 物体 A(玩家角色)

    :我们用“中心+半尺寸”来描述。

    • 中心点​C_{A}=(2,3,5)
    • 半尺寸 ​H_{A}=(1,2,1)(代表半宽1,半高2,半深1)
  • 物体 B(场景里的一个木箱)

    • 中心点 ​C_{B}=(4,4,6)
    • 半尺寸 ​C_{B}=(1.5,1,1.5)
判定步骤:
🔴使用中心距离法

对于每一个轴,我们计算两个中心点在该轴上的绝对距离,然后与两个半尺寸之和进行比较。如果距离 ≤ 半尺寸之和,说明该轴重叠。

1. 检查 X 轴(左右方向)

  • 中心点在 X 轴的距离: ​∣CxA−CxB∣=∣2−4∣=2
  • X 轴的“安全半径之和”: ​HxA+HxB=1+1.5=2.5
  • 判定:因为 2≤2.5 ,所以 X 轴重叠。(玩家和箱子在左右方向上有交集)

2. 检查 Y 轴(上下方向)

  • 中心点在 Y 轴的距离: ​∣CyA−CyB∣=∣3−4∣=1
  • Y 轴的“安全半径之和”: ​HyA+HyB=2+1=3
  • 判定:因为 1≤3 ,所以 Y 轴重叠。(玩家和箱子在上下方向上有交集)

3. 检查 Z 轴(前后方向,通常是 3D 游戏的深度)

  • 中心点在 Z 轴的距离: ​∣CzA−CzB∣=∣5−6∣=1
  • Z 轴的“安全半径之和”: ​HzA+HzB=1+1.5=2.5
  • 判定:因为 1≤2.5 ,所以 Z 轴重叠。(玩家和箱子在前后方向上有交集)

最终结论:因为 X、Y、Z 三个轴同时重叠,所以玩家角色和木箱在 3D 空间中发生了碰撞

如果用“极值表示法”怎么算?(区间交集法)

有些游戏引擎(如早期的物理系统)喜欢用最小/最大点来计算。它的数学本质是一维区间的交集判定

假设我们已知:

  • 物体 A 的 X 轴区间是 [1,3] (即 ​Cx−Hx​Cx+Hx
  • 物体 B 的 X 轴区间是 [2.5,5.5]

X 轴重叠的数学条件
​Amax≥Bmin 并且 ​Amin≤Bmax
代入数据:3≥2.5 (成立) 且 1≤5.5 (成立)。所以 X 轴重叠。
Y 轴和 Z 轴同理推算。

🔴圆形与轴对齐包围盒碰撞 (Circle vs AABB)

“圆形与轴对齐包围盒碰撞”(在 2D 中是 圆 vs 矩形,在 3D 中是 球体 vs 长方体)是游戏开发中最经典、也最能体现数学优雅之美的碰撞检测之一。

它的核心数学思想非常巧妙:它不直接计算两个复杂形状的交集,而是通过“降维转化”,把“形状 vs 形状”的问题,变成了最简单的“点 vs 形状”的问题。

下面我们以 2D(圆 vs 矩形)为主线进行深度拆解,并在最后说明如何无缝扩展到 3D。


一、 我们需要哪些数据?

为了计算方便,我们通常采用以下数据表示法:

  1. 圆形 (Circle)
    • **圆心 **​C:坐标 ​(c_x, c_y)
    • **半径 **​r:一个标量数值。
  2. 轴对齐包围盒 (AABB / 矩形)
    • 这里使用极值表示法最直观。
    • **最小点 **​P_{min}​(min_x, min_y),即矩形左下角的坐标。
    • **最大点 **​P_{max}​(max_x, max_y),即矩形右上角的坐标。

二、 核心数学原理:寻找“最近点”

想象一下,如果圆和矩形发生了碰撞,或者它们靠得非常近,那么矩形上必然存在一个点,它是整个矩形中距离圆心“最近”的点。

我们把这个点称为 **最近点 **​P(p_x, p_y)

核心逻辑
只要我们找到了这个最近点 ​P,问题就瞬间简化了!我们只需要计算**点 ​P 到圆心 ​C 的距离 **​d

  • 如果 ​d \le r(距离小于等于半径),说明圆碰到了矩形(或者圆心已经在矩形里面了),发生碰撞
  • 如果 ​d > r,说明圆还没碰到矩形,未碰撞

那么,数学上的终极问题来了:如何不写一大堆复杂的 **if-else**,用纯数学公式直接算出这个最近点 ​P 呢?


三、 数学魔法:Clamp(钳制/截断)函数

这里需要引入一个极其重要的数学/计算机函数:Clamp(钳制)
它的作用是把一个数值“限制”在某个指定的区间 ​[min, max] 内。

数学表达式为:
​Clamp(value, min, max) = \max(min, \min(value, max))

原理解析

  1. 先用 ​\min(value, max):如果 ​value 超过了上限 ​max,就把它拉回到 ​max;否则保持原样。
  2. 再用 ​\max(min, \dots):如果上一步的结果低于下限 ​min,就把它拉回到 ​min;否则保持原样。

计算最近点 ​P 的坐标:

我们将圆心的坐标,分别在 X 轴和 Y 轴上,向矩形的边界进行 Clamp 操作:

  • ​p_x = Clamp(c_x, min_x, max_x)
  • ​p_y = Clamp(c_y, min_y, max_y)

就这么简单!通过这两个公式,我们瞬间就找到了矩形上距离圆心最近的点 ​P


四、 深度剖析:为什么 Clamp 能找到最近点?(Voronoi 区域划分)

你可能会疑惑,矩形周围有那么多点,为什么这两个简单的公式就能准确找到最近点?
这背后隐藏着解析几何中的 Voronoi 区域划分(泰森多边形/空间划分) 思想。

Clamp 函数在数学上隐式地将矩形周围的 2D 空间划分成了 9 个区域。我们来看看圆心 ​C 落在不同区域时,Clamp 是如何自动处理的:

  1. 区域 1:圆心在矩形“正上方”(对应矩形的上边)
    • ​c_x​min_x​max_x 之间,所以 ​p_x = c_x
    • ​c_y 大于 ​max_y,所以 ​p_y 被 Clamp 拉回到了 ​max_y
    • 结果:最近点 ​P 刚好是圆心正下方、矩形上边缘的垂足。完全正确!
  2. 区域 2:圆心在矩形的“左上角”外侧
    • ​c_x < min_x,所以 ​p_x 被拉回到 ​min_x
    • ​c_y > max_y,所以 ​p_y 被拉回到 ​max_y
    • 结果:最近点 ​P 刚好是矩形的左上角顶点。完全正确!
  3. 区域 3:圆心在矩形“内部”
    • ​c_x​c_y 都在区间内,Clamp 不做任何改变。
    • 结果​p_x = c_x, p_y = c_y。最近点 ​P 就是圆心 ​C 本身。此时距离 ​d = 0,因为 ​0 \le r,判定为碰撞。逻辑依然完美自洽!

总结:Clamp 函数利用最值运算,自动且优雅地处理了这 9 种几何情况(4个角、4条边、1个内部),完全不需要写任何条件分支语句。


五、 完整的数学判定流程

结合上面的原理,完整的数学推导步骤如下:

**步骤 1:求最近点 **​P

  • ​p_x = \max(min_x, \min(c_x, max_x))
  • ​p_y = \max(min_y, \min(c_y, max_y))

**步骤 2:求距离向量 **​\vec{D}

  • 计算从最近点 ​P 指向圆心 ​C 的向量:​\vec{D} = C - P
  • 即:​D_x = c_x - p_x​D_y = c_y - p_y

步骤 3:距离平方比较(核心优化)

  • 根据勾股定理,真实距离 ​d = \sqrt{D_x^2 + D_y^2}
  • 判定条件是 ​d \le r
  • 数学优化:因为两边都是非负数,根据不等式的单调性,两边同时平方,消除耗时的开根号运算。
  • 最终判定条件变为:​D_x^2 + D_y^2 \le r^2

如果该不等式成立,则发生碰撞。


六、 无缝扩展到 3D 空间(球体 vs 长方体)

在 3D 游戏中(如角色球体碰撞体撞击墙壁),原理完全一模一样,仅仅是多了一个 Z 轴(深度)的维度。

3D 所需数据

  • 球体:圆心 ​C(c_x, c_y, c_z),半径 ​r
  • AABB:最小点 ​(min_x, min_y, min_z),最大点 ​(max_x, max_y, max_z)

3D 判定步骤

  1. 三维 Clamp 求最近点
    • ​p_x = Clamp(c_x, min_x, max_x)
    • ​p_y = Clamp(c_y, min_y, max_y)
    • ​p_z = Clamp(c_z, min_z, max_z)
  2. 求距离向量
    • ​D_x = c_x - p_x, \quad D_y = c_y - p_y, \quad D_z = c_z - p_z
  3. 三维距离平方比较
    • 判定条件:​D_x^2 + D_y^2 + D_z^2 \le r^2

在 3D 空间中,Clamp 函数隐式地将空间划分成了 27 个区域(3x3x3),包括 1 个内部、6 个面、12 条边、8 个角。而数学公式依然只有寥寥几行,这就是数学降维打击的威力。


七、 总结:用到的核心数学知识

  1. 分段函数与最值函数 (Min/Max):构建 Clamp 函数,实现坐标的边界截断。
  2. 空间区域划分 (Voronoi Regions):理解算法背后的几何意义,明白为什么简单的公式能覆盖所有碰撞情况(角、边、面、内部)。
  3. 向量代数 (Vector Algebra):利用向量减法计算两点间的相对位置向量。
  4. 欧几里得距离与勾股定理 (Euclidean Distance):计算空间两点间的直线距离。
  5. 不等式变换 (Inequality Transformation):利用平方操作消除根号,将复杂的无理数比较转化为简单的整数/浮点数多项式比较。

🔴有向包围盒(OBB, Oriented Bounding Box)碰撞

课程1

相比于“永远横平竖直”的 AABB,有向包围盒(OBB, Oriented Bounding Box) 解除了“不能旋转”的封印。它可以随着游戏物体任意旋转、倾斜,从而更紧密地贴合物体的真实轮廓。

但也正因为 “能旋转” ,AABB 那套简单的“比较 X/Y/Z 最大最小值”的方法彻底失效了。为了检测两个任意旋转的 OBB 是否碰撞,我们需要引入碰撞检测领域最著名、也最优雅的数学定理:分离轴定理(SAT, Separating Axis Theorem)

下面我们从 2D 到 3D,把 OBB vs OBB 的碰撞检测彻底拆解。


一、 在数学上,如何描述一个 OBB?

因为 OBB 可以旋转,我们不能再用简单的“世界坐标下的最小/最大点”来描述它了。在引擎底层,一个 OBB 通常由以下三组数据定义:

  1. **中心点 **​C:几何中心的坐标 ​(c_x, c_y, c_z)
  2. **半尺寸 **​H:在自身局部坐标系下的半宽、半高、半深 ​(h_x, h_y, h_z)
  3. 方向轴(局部坐标轴):描述它旋转姿态的单位向量。
    • 2D 中:2 个互相垂直的单位向量 ​\vec{u}, \vec{v}(代表局部的 X 轴和 Y 轴)。
    • 3D 中:3 个互相正交的单位向量 ​\vec{u}, \vec{v}, \vec{w}(通常构成一个 ​3 \times 3 的旋转矩阵)。

二、 核心数学灵魂:分离轴定理 (SAT)

分离轴定理(SAT) 的核心思想极其反直觉但非常有效:

“如果两个凸多边形(或多面体)没有相交,那么必然存在至少一条直线(或平面),能够将它们完全分隔在两侧。这条线/面就是‘分离轴’。”

反过来说(判定碰撞的逻辑)

如果我们检查了所有“可能”成为分离轴的候选轴,发现两个物体在每一条轴上的投影都发生了重叠,那么这两个物体必然发生了碰撞

注:AABB 其实就是 SAT 的特例。因为 AABB 永远对齐世界坐标轴,所以它的“候选轴”永远只有固定的世界 X、Y、Z 轴。而 OBB 旋转了,所以我们需要动态去寻找这些“候选轴”。


三、 2D 空间实战:旋转矩形 vs 旋转矩形

假设我们在 2D 平面上有两个任意旋转的矩形(OBB A 和 OBB B)。

步骤 1:寻找“候选分离轴”

在 2D 中,两个凸多边形如果分离,分离线必然平行于其中某个多边形的一条边。因此,候选轴就是这两个矩形各条边的“法线(垂直线)”

  • 矩形 A 有 4 条边,提取出 2 个独立的法线轴:​\vec{A_1}, \vec{A_2}(即 A 的局部 X 轴和 Y 轴)。
  • 矩形 B 有 4 条边,提取出 2 个独立的法线轴:​\vec{B_1}, \vec{B_2}(即 B 的局部 X 轴和 Y 轴)。
    结论:在 2D 中,我们只需要检查 4 条候选轴​\vec{A_1}, \vec{A_2}, \vec{B_1}, \vec{B_2})。

步骤 2:将两个 OBB 投影到候选轴上

对于每一条候选轴(假设为单位向量 ​\vec{L}),我们需要把矩形 A 和矩形 B 都“拍扁”投影到这条轴上,得到两条一维线段。

数学投影计算
一个 OBB 在某条轴 ​\vec{L} 上的投影,可以看作是一个中心点投影加上一个“投影半径”。

  1. 中心点投影:将 OBB 的中心点 ​C 点乘候选轴 ​\vec{L},得到投影中心 ​p = C \cdot \vec{L}
  2. **投影半径 **​r:OBB 在轴 ​\vec{L} 上占据的“半宽”。利用 OBB 的局部轴和半尺寸计算:
    ​r = h_x |\vec{u} \cdot \vec{L}| + h_y |\vec{v} \cdot \vec{L}|
    (这里的点乘取绝对值,是因为我们要计算的是最大延伸距离)

步骤 3:检查一维线段是否重叠

现在我们有了 A 的投影区间 ​[p_A - r_A, p_A + r_A] 和 B 的投影区间 ​[p_B - r_B, p_B + r_B]
它们重叠的数学条件非常简单:
两个投影中心的距离 ​\le 两个投影半径之和
即:​|p_A - p_B| \le r_A + r_B

最终判定:

依次检查这 4 条轴。

  • 如果在任意一条轴上,​|p_A - p_B| > r_A + r_B(找到了分离轴),立刻停止计算,未碰撞
  • 如果 4 条轴全部重叠发生碰撞

四、 升维打击:3D 空间中的 OBB vs OBB

到了 3D 空间,情况变得复杂得多。两个 3D 长方体(OBB)如果分离,分离面可能平行于 A 的面、平行于 B 的面,还可能平行于 A 的一条边和 B 的一条边所构成的平面(边-边分离)

因此,3D 中的“候选分离轴”数量暴增到了 15 条

1. 寻找 15 条候选轴

假设 OBB A 的局部轴为 ​\vec{A_x}, \vec{A_y}, \vec{A_z},OBB B 的局部轴为 ​\vec{B_x}, \vec{B_y}, \vec{B_z}

  • A 的 3 个面法线​\vec{A_x}, \vec{A_y}, \vec{A_z} (3条)
  • B 的 3 个面法线​\vec{B_x}, \vec{B_y}, \vec{B_z} (3条)
  • A 的边与 B 的边的叉乘(边-边轴)​\vec{A_i} \times \vec{B_j}​3 \times 3 = 9 条)
    总计:3 + 3 + 9 = 15 条候选轴。

(注:叉乘 ​\times 的几何意义是求出一个同时垂直于两个向量的法向量,正好代表了“边-边”构成的分离平面的法线。)

2. 投影与重叠检测(3D 版)

对于这 15 条轴中的每一条(设为 ​\vec{L}),计算逻辑与 2D 完全一致:

  1. 计算投影中心距离:​D = |(C_B - C_A) \cdot \vec{L}|
  2. 计算 A 的投影半径:​r_A = h_{Ax}|\vec{A_x}\cdot\vec{L}| + h_{Ay}|\vec{A_y}\cdot\vec{L}| + h_{Az}|\vec{A_z}\cdot\vec{L}|
  3. 计算 B 的投影半径:​r_B = h_{Bx}|\vec{B_x}\cdot\vec{L}| + h_{By}|\vec{B_y}\cdot\vec{L}| + h_{Bz}|\vec{B_z}\cdot\vec{L}|
  4. 判断:如果 ​D > r_A + r_B,则分离,未碰撞

如果 15 条轴全部检测完都没有分离,则发生碰撞


五、 引擎底层的极限优化:相对投影法

如果直接按上面的公式算 15 条轴,需要做大量的向量点乘和叉乘,性能开销很大。现代物理引擎(如 Box2D, PhysX)会使用相对坐标系进行极限优化。

核心思想:把 OBB B 转换到 OBB A 的局部坐标系中。

  1. 计算相对位置向量 ​\vec{T} = C_B - C_A
  2. 计算 B 的局部轴在 A 的局部坐标系下的表示(通过矩阵乘法或点乘),得到一个 ​3 \times 3 的**旋转相对矩阵 **​R
    ​R_{ij} = \vec{A_i} \cdot \vec{B_j}
  3. 利用矩阵 ​R 和相对位置 ​\vec{T},可以将 15 次投影计算转化为简单的查表和代数加减法,彻底消除运行时的三角函数和复杂的向量运算。

六、 总结:OBB 碰撞背后的数学知识库

OBB vs OBB 是游戏物理引擎中最基础也最硬核的算法之一,它几乎调动了线性代数的所有核心工具:

  1. 分离轴定理 (SAT):将复杂的 3D 体积相交问题,转化为多个 1D 线段重叠问题的核心指导思想。
  2. 向量点乘 (Dot Product):用于计算向量在某个轴上的“投影长度”(​a \cdot b = |a||b|\cos\theta)。
  3. 向量叉乘 (Cross Product):用于在 3D 空间中寻找“边-边”分离轴(求两个方向向量的公垂线)。
  4. 矩阵与基变换 (Matrix & Change of Basis):通过构建相对旋转矩阵,将一个物体的坐标转换到另一个物体的局部空间,从而实现计算降维和性能优化。
  5. 绝对值与不等式:用于处理投影时的方向无关性,以及最终的 1D 区间重叠判定。

一句话总结
AABB 碰撞是“比大小”,Circle vs AABB 是“找最近点”,而 OBB 碰撞则是“在 15 个特定方向上玩 1D 投影重叠游戏”

课程2

OBB(Oriented Bounding Box,有向包围盒)碰撞,本质上是在解决:

“两个任意旋转的矩形/盒子是否相交”。

它比 AABB(轴对齐包围盒)难很多,因为:

  • AABB 永远和世界坐标轴平行
  • OBB 可以任意旋转

所以:

不能再用简单的 x/y/z 区间重叠判断

而 OBB 的核心数学原理,其实只有一个:

分离轴定理(SAT)


一、SAT 的真正思想

SAT(Separating Axis Theorem)说:

如果两个凸物体没有碰撞,那么一定存在一条轴,使它们在这条轴上的投影不重叠。

反过来:

如果所有可能轴上的投影都重叠,那么它们一定碰撞。

这是 OBB 的整个数学基础。

注意关键词:

“投影”

因为:

碰撞问题被转化成了“一维区间重叠问题”

这就是 SAT 最厉害的地方。


二、为什么“投影”能判断碰撞?

先想二维。

假设两个旋转矩形:

A
B

很难直接判断。

但如果你拿一条轴,例如:

然后把两个矩形都“压扁”到这条线上。

你会得到:

线段区间

例如:

A: [2,5]
B: [6,8]

如果区间不重叠:

说明一定没碰撞

因为:

存在“空隙”

这条轴就叫:

分离轴

三、为什么只检查特定轴?

这是 SAT 最关键的数学结论。

二维 OBB 只需要检查:

  • A 的两个边法线
  • B 的两个边法线

总共:

4 条轴

因为:

如果两个凸多边形存在分离轴,那么它一定垂直于某条边。

这是凸几何的重要定理。


四、OBB 的数据结构

二维 OBB 一般包含:

center
halfExtents
rotation

也可以写成:

center
axisX
axisY
halfWidth
halfHeight

其中:

  • center:中心点
  • axisX:盒子右方向
  • axisY:盒子上方向

注意:

axisX / axisY 必须是单位向量

因为它们本质是:

局部坐标轴

五、投影真正怎么计算?

现在来到核心。

假设有一条检测轴:

L

单位向量。

我们要计算:

OBB 在 L 上的投影范围

六、为什么点积能做投影?

因为点积:

​a\cdot b=|a||b|\cos\theta

本质就是:

一个向量在另一个方向上的投影长度。

所以:

点积 = 投影

七、OBB 投影半径公式

这是 SAT 最核心公式之一。

二维 OBB 在轴 L 上的投影半径:

r=e_x|L\cdot A_x|+e_y|L\cdot A_y|

这里:

  • e_x:半宽
  • e_y:半高
  • A_x:OBB 的 x 轴
  • A_y:OBB 的 y 轴

八、这个公式为什么成立?

这是真正数学本质。

OBB 可以看成:

两个轴方向的组合

即:

横向贡献 + 纵向贡献

现在:

我们想知道:

这个盒子在 L 上能延伸多远

于是:

  • 横轴在 L 上的投影长度
  • 纵轴在 L 上的投影长度

加起来。


横向贡献:

​e_x|L\cdot A_x|

纵向贡献:

​e_y|L\cdot A_y|

相加后:

​r=e_x|L\cdot A_x|+e_y|L\cdot A_y|

这就是投影半径。


九、真正碰撞判断

现在:

两个 OBB:

A
B

中心差:

​T=C_B-C_A

投影到轴 L

​d=|T\cdot L|

得到:

两个中心在轴上的距离

然后:

如果:

​d>r_A+r_B

说明:

出现分离

即:

没有碰撞

否则继续检查下一条轴。


十、二维 OBB 为什么只检查 4 条轴?

因为矩形边只有两种方向:

  • x轴方向
  • y轴方向

法线也只有两种。

两个矩形:

2 + 2 = 4

十一、三维 OBB 更复杂

3D OBB vs OBB 需要检查:

  • A 的 3 个轴
  • B 的 3 个轴
  • 两两叉积生成的 9 个轴

总共:

15 条轴

即:

3 + 3 + 9

十二、为什么还要检查叉积轴?

因为在三维里:

边与边之间可能形成新的分离方向

二维不存在这个问题。


十三、OBB 为什么比 AABB 贵?

AABB:

只比较 min/max

OBB:

大量 dot

因为 SAT 本质上是:

不停做向量投影

十四、为什么游戏引擎很少直接大量用 OBB?

因为:

太贵

通常:

  • Broad Phase:AABB
  • Narrow Phase:OBB / SAT / GJK

先粗筛。


十五、你现在真正应该理解的核心

OBB vs OBB 本质不是:

“盒子碰撞”

而是:

“凸体在不同轴上的投影是否分离”

整个算法核心只有三件事:


1. 选轴

SAT。


2. 点积投影

因为:

dot = 投影长度

3. 区间重叠

如果:

所有轴都重叠

则碰撞。


这就是 OBB 的真正数学原理。

🔴 GJK

0

评论区