KDOP+BVH 碰撞检测算法
在计算机图形学、物理引擎以及求解器中的接触/绑定搜索(Contact / Tie Search)中,包围盒(Bounding Box)是加速几何查询和剔除无关计算的核心技术。常见的包围盒有 AABB(轴对齐包围盒)、OBB(定向包围盒)和K-DOP(Discrete Oriented Polytope,离散定向多胞体) 。其中,AABB(Axis-Aligned Bounding Box)其实是 K-DOP 的一种特例,即6-DOP。
K-DOP 的定义
k-DOP 可以理解为:用一组固定方向上的平行平面把几何体包起来。
如果有 k 个边界平面,就有 k/2 个方向。随着 k 值的增加,K-DOP 会包含更多方向的平面,从而能更紧密地包裹物体,但也会增加碰撞检测的计算开销。
下表列出了几个常见的K-DOP。
| 包围盒类型 | k 值 | 示意图 | 特点与适用场景 |
|---|---|---|---|
| AABB | 6 | ![]() |
构建与碰撞检测速度最快,但对倾斜物体的包裹性较差。 |
| 14-DOP | 14 | ![]() |
切去立方体的 8 个角,提供更好的紧密度。 |
| 18-DOP | 18 | ![]() |
切去立方体的 12 条棱,常用于复杂几何体的高效碰撞剔除。 |
| 26-DOP | 26 | ![]() |
包裹极其紧密,接近凸包,常用于高精度物理碰撞检测。 |
在代码实现上,每个方向 d_i 可以用两个点表示:
min_i = min(d_i · p)
max_i = max(d_i · p)
所以一个 k-DOP 实际存的是:
[min_0, max_0]
[min_1, max_1]
...
[min_{k/2-1}, max_{k/2-1}]
其中
- \(p\) 是输入的模型顶点坐标(变量,来自网格数据)。
- \(d_i\) 是预先设定好的投影方向(常量,决定了包围盒的形状类型)。
min_i与max_i保存了整个模型在 \(d_i\) 方向上的“最远边界”,由这 \(k/2\) 对区间共同夹出的空间,就是该物体的 K-DOP 包围盒
两个 k-DOP 的碰撞判断
碰撞检测很简单。两个物体在方向 (d_i) 上的投影区间分别为:
只要任意一个方向上的区间不相交:

两个 k-DOP 就一定不相交。只有所有方向上的区间都重叠,才认为包围体重叠,进入后续精确接触检测。

BVH + k-DOP 搜索
单独 k-DOP 只能判断两个对象是否可能相交。为了避免所有面元两两比较,需要把 k-DOP 放进 BVH,然后进行接触搜索。BVH(Bounding Volume Hierarchy) 是一种在计算机图形学中广泛使用的空间加速数据结构。它实际上是一种树结构,叶节点对应一个真实的面单元,根节点包围整个表面,内部节点的包围体包含其所有子节点。

BVH 节点可以定义成
struct BvhNode {
BoundingVolume bounding_volume;
int left_child;
int right_child;
int entry_index; // 仅叶节点有效
};
判断是否为叶节点的方法是:
bool IsLeaf() const
{
return m_entry_index != kBadIndex;
}
因此有两种节点状态:
叶节点:
entry_index = 表面单元索引
left/right = 无效
bounding_volume = 该单元的 k-DOP
内部节点:
entry_index = 无效
left/right = 两个子节点索引
bounding_volume = 两个子树包围体的并集
树的构建过程是:
- 给每个表面单元建立叶节点包围体
- 根据单元中心坐标选择划分轴
- 用 SAH 代价 ( Surface Area Heuristic ) 选择最佳分割位置
- 递归构建左右子树
- 将子树包围体合并为父节点包围体
两个 BVH 做碰撞搜索时,从两个根节点开始:
(rootA, rootB)
|
├─ 包围体不重叠:整对子树全部丢弃
|
└─包围体重叠:
|
├─ 都是叶节点:输出候选单元对
|
└─ 至少一个是内部节点:展开子节点继续比较
两个表面单元的包围体重叠不能说明表面真的接触,后面还需要做精筛。
参考文献
[1] https://blog.csdn.net/zhanxi1992/article/details/127462494





浙公网安备 33010602011771号