构建一个高质量的 AABB Tree (轴对齐包围盒树) 是粗略阶段碰撞检测效率的基础。构建策略的目标是让树尽可能的平衡(深度小)和尽可能的紧凑(节点 AABB 的体积小),从而在查询时能快速排除大量不相关的分支。
下面详细介绍两种主要的树构建策略:自顶向下 (Top-Down) 和 自底向上 (Bottom-Up),以及优化构建质量的表面积启发式 (SAH)。
🌳 1. 自顶向下构建 (Top-Down Construction)
这是最常用且最直观的构建方法,尤其适用于初始构建。
📌 策略步骤
-
从根节点开始: 根节点 AABB 包围整个场景或所有待处理的几何图元(三角形、顶点或刚体)。
-
选择分割轴: 在当前节点的 AABB 上,选择最长的那个轴(X、Y 或 Z)作为当前的分割轴。
-
选择分割位置:
- 中位数分割 (Median Split): 找到图元在选定轴上的几何中心或质心的中位数。将图元分成左右(或上或下)数量大致相等的两组。
- 空间中点分割 (Midpoint Split): 找到当前节点 AABB 在选定轴上的几何中点。按这个中点将空间分成两部分,图元则根据其几何中心落入哪部分而归类。
-
递归创建子节点:
- 为分割后的两组图元分别创建左子节点和右子节点。
- 计算每个新子集对应的 AABB。
- 对每个子节点重复步骤 2 至 4,直到满足终止条件(如:节点内的图元数量小于预设的阈值,例如 8 或 16 个;或 AABB 的体积已经非常小)。
💡 优点与缺点
| 优点 | 缺点 |
|---|---|
| 易于实现: 逻辑直观,代码相对简单。 | 局部最优: 通常只寻找当前分割轴上的最佳分割点,可能错过全局最优。 |
| 平衡性好: 中位数分割能保证图元数量的平衡,从而保证树的深度较小。 | AABB 体积可能较大: 空间中点分割可能导致子节点的 AABB 包含大量空隙(如果图元分布不均匀)。 |
📐 2. 表面积启发式 (Surface Area Heuristic, SAH)
SAH 不是一种独立的构建方法,而是一种优化分割位置的准则,通常与自顶向下构建结合使用。它能显著提高树的几何质量。
📌 原理
SAH 的目标是最小化遍历碰撞查询时的预期成本。它基于以下假设:如果一个 AABB 的表面积越小,光线(或另一个 AABB)击中它的概率就越小。
SAH 将分割平面的成本定义为:
其中:
- : 遍历当前节点的固定成本。
- : 一个查询与左子节点 AABB 相交的概率(近似于 )。
- : 如果进入左子节点,剩余的查询成本(通常正比于左子节点内的图元数量 )。
- : 对应于右子节点。
构建过程: 对于每个节点,SAH 会尝试:
- 遍历所有轴(X、Y、Z)。
- 在每个轴上,尝试多个候选分割位置(通常是图元 AABB 的最小/最大边界)。
- 计算所有候选分割位置的成本,并选择成本最低的那个轴和位置作为最终分割点。
💡 优点与缺点
| 优点 | 缺点 |
|---|---|
| 最高质量: 生成的树通常具有最佳的查询性能。 | 构建成本高: 需要尝试和评估多个分割点,构建时间比简单中位数分割慢得多。 |
| 几何紧凑: 优先选择能形成紧凑子 AABB 的分割,避免了大量空隙。 | 复杂性: 实现 SAH 需要更复杂的逻辑来管理候选分割点和计算表面积。 |
🏗️ 3. 自底向上构建 (Bottom-Up Construction)
此方法不常用作初始构建,但概念上很重要,有时用于局部重建或简化。
📌 策略步骤
- 从叶子开始: 首先为每个图元创建一个叶子节点 AABB。
- 迭代合并: 在每一步中,找到所有未合并的节点中“距离最近”或“合并后体积增长最小”的一对节点 。
- 创建父节点: 创建一个新的父节点 ,其 AABB 包围 和 的 AABB。然后将 加入未合并的节点集合。
- 重复: 重复步骤 2 和 3,直到只剩下一个节点(根节点)。
💡 优点与缺点
| 优点 | 缺点 |
|---|---|
| 紧凑性好: 合并最近的 AABB 保证了节点 AABB 的紧凑性。 | 平衡性差: 贪心的合并策略可能会导致树非常深且不平衡,影响查询效率。 |
| 局部最优: 对于处理少量局部变动的物体(局部重构)可能有效。 | 实现复杂: 找到最佳的合并对需要 或 的搜索,对于大规模场景效率低下。 |
✨ 总结:构建策略选择
| 场景 | 推荐策略 | 重点关注 |
|---|---|---|
| 静态场景 (光线追踪) | 自顶向下 + SAH | 查询速度是最高的优先级,可接受较长的构建时间。 |
| 动态场景 (游戏/物理模拟) | 自顶向下 + 中位数分割 (初始) | 构建速度和动态更新速度是关键。 |
| 动态场景 (更新) | Incremental Refitting (渐进式重构) 或 Fattened AABBs (增肥) | 在每帧只更新移动物体的 AABB 及其父节点,并使用旋转或局部重建来保持平衡。 |
- AABB Tree 构建策略的分类
- 自顶向下与 SAH 策略
- 自底向上策略
- DBVT (Bullet Physics) 的动态构建策略
🌳 物理模拟中 AABB Tree/DBVT 的构建策略
物理模拟的粗略阶段(Broad Phase)严重依赖 层次包围体系统 (BVH),特别是 AABB Tree 或其动态变体 DBVT。构建一个高质量的树是保证查询效率的关键。
1. 结构划分与构建策略总览
构建策略可以根据其处理图元的方式分为两大类:
| 策略类别 | 特点 | 典型应用 |
|---|---|---|
| 自顶向下 (Top-Down) | 从根节点开始,递归地将图元集合分割成两个子集。 | 静态场景的初始构建(光线追踪)。 |
| 自底向上 (Bottom-Up) | 从叶子节点开始,迭代地合并“最近”或“最相似”的节点对。 | 局部重构或简化。 |
| 增量/贪婪插入 (Incremental/Greedy) | 逐个插入或更新物体,并局部优化插入路径。 | 动态场景,如 Bullet Physics 的 DBVT。 |
2. 静态构建策略(自顶向下)
这是最常用且最直观的构建方法。
2.1. 中位数分割 (Median Split)
- 原理: 沿着 AABB 的最长轴,找到图元在选定轴上几何中心的中位数。根据中位数将图元分成数量大致相等的两组。
- 目标: 保证树的平衡性,使得树的深度最小 ()。
- 局限性: 仅追求图元数量上的平衡,可能导致子节点 AABB 体积不紧凑。
2.2. 表面积启发式 (Surface Area Heuristic, SAH) 📐
SAH 是一种优化分割位置的准则,旨在构建几何质量最高的树。
- 目标: 最小化遍历碰撞查询时的预期成本,即最小化子节点的 AABB 表面积之和。
- 成本函数: 评估将当前节点 划分成 和 的成本:
- 策略: 尝试所有轴,并在每个轴上尝试多个分割位置,最终选择成本最低的分割点。
- 应用: 主要用于静态场景或高精度光线追踪,因为它构建时间较长但查询性能最优。
3. 动态构建策略:DBVT (Bullet Physics)
Bullet Physics 主要采用 动态层次包围盒树 (DBVT),其构建策略的核心是高效的增量更新和贪婪优化。
3.1. 核心策略:贪婪插入 (Greedy Insertion)
DBVT 的构建和更新是增量式的,而不是一次性完全构建。它不使用中位数分割,因为中位数分割的计算成本对于动态更新来说太高 ()。
- 决策依据: 最小体积增长启发式 (Minimum Volume Increase)。
- 原理: 在插入一个新的 AABB () 时,算法从根节点向下遍历,在每一步都选择能导致当前节点 AABB 体积增量最小的子节点继续递归。
- 优势: 保证了树结构在每次更新后都能保持局部几何紧凑性,且更新复杂度为 ,适用于实时物理模拟。
3.2. 增肥 AABB (Fattened AABBs) 🧈
增肥 AABB 是动态更新的关键优化,它通过扩大叶子节点的 AABB 来延迟触发结构更新,提高整体性能。
- 更新触发: 只有当物体的实际 AABB 移动出其增肥 AABB 时,才执行移除和重新插入操作。
- 流程: 一旦触发更新,物体对应的叶子节点会被移除,然后使用贪婪插入策略重新定位。
4. 自底向上构建 (Bottom-Up Construction)
- 原理: 从单独的叶子节点开始,迭代地寻找并合并当前集合中“距离最近”或“合并后体积增长最小”的一对节点,直到只剩下一个根节点。
- 特点: 保证了紧凑性(因为总是合并最近的),但由于贪婪的合并策略,通常会导致树的平衡性较差。
- 应用: 不常用于实时碰撞检测的初始构建,但可用于局部重构或静态场景的预处理。
希望这份整理能帮您更好地理解这些构建策略的区别与应用!您对 Bullet Physics 的 DBVT 如何处理节点旋转以维持平衡感兴趣吗?