AABB相交的核心逻辑是三轴投影全部重叠;即x、y、z轴上两盒区间均相交才相交,任一轴分离则不相交,无需考虑旋转或顶点计算。

判断AABB相交的核心逻辑是什么
两个AABB是否相交,只取决于它们在x、y、z三个轴上投影是否全部重叠。只要任一轴上不重叠,就完全不相交;三轴都重叠,才真正相交。这是AABB(Axis-Aligned Bounding Box)最根本的性质,和旋转无关,也不需要计算面或顶点。
实践中,用“分离轴定理”的简化版:对每个轴检查两个盒的区间是否相交。比如x轴上,若box1.max_x 或 <code>box1.min_x > box2.max_x,就分离了。
C++中用min/max成员变量实现相交检测
假设每个AABB用两个glm::vec3(或自定义结构体)表示:min和max,且满足min[i] 。检测函数通常长这样:
bool intersects(const AABB& a, const AABB& b) {
return a.min.x <= b.max.x && b.min.x <= a.max.x &&
a.min.y <= b.max.y && b.min.y <= a.max.y &&
a.min.z <= b.max.z && b.min.z <= a.max.z;
}
注意顺序:不是a.min.x ,而是<code>——边界接触(如一个盒的<code>max_x == b.min_x)算相交。这是几何上“闭区间重叠”的标准定义。
立即学习“C++免费学习笔记(深入)”;
- 如果用
float坐标,浮点误差可能导致本应接触的盒被误判为不相交;必要时加极小容差(如+ 1e-5f),但要小心容差过大引发误报 - 若AABB未归一化(即
min各分量未必全小于max),需先调用normalize()或手动交换 - GLM用户可直接用
glm::intersect,但它针对glm::aabb类型(C++20起),旧版本无此函数,别硬查文档
用std::array或结构体封装时的常见错误
有人把AABB写成std::array<glm::vec3, 2>,索引0是min、1是max,但容易在传参或比较时写反顺序,比如:
// ❌ 错误:把max当min用 return a[0].x <= b[1].x && b[0].x <= a[1].x; // 这里a[0]本该是min,但如果初始化错就崩
更安全的做法是显式命名:
- 用结构体而非裸数组:
struct AABB { glm::vec3 min, max; }; - 构造函数强制校验:
AABB(glm::vec3 m, glm::vec3 M) : min(glm::min(m, M)), max(glm::max(m, M)) {} - 避免裸指针传
AABB*——万一为空,min.x直接崩溃
性能敏感场景下的优化提示
纯CPU端每帧检测上千对AABB时,内存布局会影响速度。若批量处理,把所有min.x、max.x等分别连续存放(SoA),比每个AABB内部存(AoS)更容易向量化。
但对一般游戏逻辑或单次检测,不用过早优化。重点是别在循环里重复计算glm::min/glm::max——这些值应预存,而非每次从8个顶点实时生成。
真正容易被忽略的是坐标系一致性:一个盒用右手系Z-up,另一个用左手系Y-up,min/max直接比较毫无意义。做相交前,确保所有AABB已转换到同一空间(如世界坐标)。


















