AABB碰撞判定只需检查x、y轴投影是否同时重叠,即(a.min_x b.min_x) && (a.min_y b.min_y),该式简洁高效且天然支持退化情况。

用分离轴定理(SAT)最简形式判断 AABB 碰撞
AABB 碰撞本质就是:两个矩形在 x 轴和 y 轴上投影都重叠,才可能相交。只要任一轴上投影分离,就一定没碰撞。C++ 里直接比坐标更高效,不用构造向量或调用几何库。
假设每个 AABB 用 min_x、max_x、min_y、max_y 表示(左下为 min,右上为 max),那么:
- 不碰撞的条件是:
rectA.max_x 或rectA.min_x > rectB.max_x或rectA.max_y 或rectA.min_y > rectB.max_y - 所以碰撞条件就是这四个不等式的逻辑非:用
!包一层,或直接写成全“与”关系 - 推荐写法(清晰且利于编译器优化):
bool intersect = (a.min_x b.min_x) && (a.min_y b.min_y);
注意坐标系方向和 min/max 定义一致性
很多 bug 出在“你以为的 min 是真的 min”。比如 OpenGL 窗口坐标中 y 向下增长,而数学坐标系 y 向上,若混用会导致 min_y > max_y 的诡异情况,使碰撞永远为 false。
实操建议:
- 统一用“左下为
min,右上为max”约定,无论实际渲染方向如何,内部计算保持该语义 - 在构造 AABB 时做一次校验:
assert(a.min_x ,避免传入乱序坐标 - 如果输入是中心点 + 半宽高(如
center_x,half_w),务必显式转成 min/max:min_x = center_x - half_w; max_x = center_x + half_w;
浮点精度下要不要加 epsilon?
纯整数坐标(如像素格子)完全不需要 epsilon;但涉及物理模拟、动画插值等场景,浮点运算会累积误差,导致本应接触的 AABB 被判定为“刚好不碰”。
这时可加极小偏移,但注意方式:
- 错误做法:对所有比较加
+ 1e-6,会扩大碰撞判定范围,引发误触 - 正确做法:只在“相等即视为接触”的边界上松动,例如把
a.max_x > b.min_x改为a.max_x + eps > b.min_x,其他三边同理 - 更稳妥的是用
std::nextafter获取浮点后继值,避免 magic number:auto eps = std::nextafter(a.max_x, INFINITY);
再用于比较
性能敏感场景下的内联与结构体对齐
每帧要检测上千次 AABB 碰撞时,函数调用开销和内存布局会影响速度。
- 把判定逻辑写成
inline函数,或直接展开在热路径中 - AABB 结构体成员按大小降序排列(
double或float四字段),避免因填充浪费 cache line - 如果批量处理,考虑用 SIMD 对四组 AABB 同时做 x 轴比较(需 SSE/AVX 支持),但单次判断没必要过度优化
真正容易被忽略的是:当矩形退化为线段(min_x == max_x)或点时,上述公式仍成立——它天然支持零面积情况,不必额外分支处理。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











