快速判断两个aabb是否相交:只需检查x、y(及z)轴投影是否同时重叠;任一轴分离(如a.max.x
怎么快速判断两个 AABB 是否相交
两个 AABB(Axis-Aligned Bounding Box)是否碰撞,本质是判断它们在 x 和 y(以及 z,若为 3D)三个轴上投影是否同时重叠。只要有一个轴不重叠,就一定没碰撞 —— 这是分离轴定理(SAT)在轴对齐情况下的最简应用。
二维下只需检查两组区间是否都相交:
rect1.x与rect1.x + rect1.width构成的 x 区间,和rect2.x与rect2.x + rect2.width的 x 区间;y 方向同理。
- 别用中心点加半宽/半高去算 —— 容易因浮点误差或负尺寸出错,直接用左边界+宽更稳
- 注意:AABB 通常定义为
left,top,width,height,但有些库用min/max坐标(如min.x,max.x),此时判断更直白:! (a.max.x- 如果矩形可能宽/高为负(比如由鼠标拖拽生成,未归一化),先调用
std::minmax对角点做归一化再判断,否则结果不可靠为什么用 “不相交” 条件写判据更安全
主流实现都写成「若分离则返回 false」,而不是「若相交则返回 true」,因为分离条件逻辑更少、分支更清晰、不易漏边。
例如,x 轴分离的充要条件是:
rect1.right (其中 <code>right = left + width)。y 轴同理。只要任一轴分离,就无碰撞。
- 错误写法:
if (x_overlap && y_overlap) return true;—— 看似自然,但x_overlap自身容易写反(比如把>=写成>),而分离式只涉及,语义明确- 浮点场景下,用
判分离边界(如 <code>a.max.x )比用 <code>>更利于控制接触判定的包容性- 若需支持“边缘接触即算碰撞”,所有比较符统一用
或 <code>>=;若需“严格重叠”,才用/ <code>>C++ 实现中 struct 成员顺序和内存布局的影响
AABB 结构体若用于高频碰撞检测(比如每帧上万次),成员排列顺序会影响缓存友好性。x 和 y 相关字段尽量连续,避免跨 cache line 读取。
典型高效布局:
struct AABB { float left, bottom; // 共享 cache line float width, height; };而非:
struct AABB { float left, width, right; // right 是冗余字段,且分散 float top, height, bottom; };
- 别存
right和bottom—— 它们可即时计算,还浪费空间、破坏 locality- 若用 SIMD 批量检测(如 AVX 处理 8 个 AABB),建议结构体按 AoS→SoA 拆解,但单次判断仍推荐紧凑 AoS
- 对齐方面:
alignas(16)对 float4 友好,但纯 AABB 四 float 已天然满足 16 字节对齐,无需额外修饰碰撞后求重叠区域(Intersect Rectangle)的常见陷阱
很多需求不止要 bool 判定,还要知道重叠部分的坐标(比如裁剪、响应偏移、物理冲量计算)。这时不能简单取 max/min —— 必须确保输入 AABB 本身是合法的(
width >= 0,height >= 0)。
- 重叠矩形的
left = std::max(a.left, b.left),right = std::min(a.left + a.width, b.left + b.width),再算width = right - left;但若width ,说明其实没重叠 —— 得先做一次碰撞判定,再算交集,否则会得到负尺寸“伪矩形”- 用
std::max/std::min时注意模板参数类型一致,混用int和float可能触发隐式转换警告甚至精度丢失- 某些图形 API(如 SDL)的
SDL_IntersectRect返回 bool 并通过指针写入结果,C++ 封装时建议用std::optional<aabb></aabb>表达“可能无交集”,比传引用+bool 返回更清晰重叠计算本身不难,难的是在 pipeline 中保持状态一致性:一旦某个 AABB 因缩放或变换暂时变成退化矩形(width=0),后续交集结果就会失效,这类边界必须在上游卡住。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!












