
核心原因是精确碰撞检测比较昂贵不能对场景中所有形状两两执行。PhysX 先用低成本方法筛选候选对再对少量候选对进行精确计算。两阶段分别回答不同的问题Broad Phase宽相 哪些形状可能发生碰撞 ↓ Narrow Phase窄相 这些形状是否形成接触 接触在哪里、法线是什么、分离距离是多少严格来说小规模场景可以直接两两检测并不是数学上“必须”分成两阶段。但对大型实时物理场景这种分工非常重要。一、为什么不能直接做精确检测假设场景中有 (N) 个碰撞形状全部两两配对的数量为[P\frac{N(N-1)}{2}]当 (N10,000) 时[P49,995,000]即接近5000 万个形状对。如果每个物理步都对这些配对进行凸体、三角网格等精确检测成本通常不可接受。而且绝大多数配对根本没有意义城市东侧的汽车 vs 城市西侧的垃圾桶它们相距几公里不应该进入精确几何计算。因此需要大量形状 ↓ 低成本空间筛选 少量候选对 ↓ 精确几何检测 有效接触二、Broad Phase用便宜的边界替代复杂形状1. 核心职责Broad Phase 不直接研究形状表面的细节而是使用包围体进行空间筛选。PhysX 的模拟宽相主要围绕AABB轴对齐包围盒工作实际碰撞形状 ↓ 包住它的世界空间 AABB ↓ 检查哪些包围盒可能重叠AABB 的三个方向始终与坐标轴平行可以用最小点和最大点表示structAABB{Vec3 min;Vec3 max;};两个 AABB 是否重叠只需要检查三个坐标轴上的区间booloverlap(constAABBa,constAABBb){returna.min.xb.max.xa.max.xb.min.xa.min.yb.max.ya.max.yb.min.ya.min.zb.max.za.max.zb.min.z;}这比复杂凸体或网格之间的精确接触生成便宜得多。2. 只是换成 AABB还不够一个容易忽视的点是如果仍然把所有 AABB 两两比较复杂度还是 (O(N^2))。因此 Broad Phase 不仅使用简单边界还使用空间组织算法避免检查大量明显不相关的配对。PhysX 不同版本和配置提供的宽相算法包括SAPSweep and PruneMBPMulti Box PruningABPAutomatic Box PruningGPU Broad Phase。例如SAP 利用坐标轴上的区间排序空间分区类方法则利用区域划分减少候选配对。Broad Phase 的价值是“便宜的表示 高效的候选搜索”不是只有包围盒。三、为什么 Broad Phase 不能直接判定碰撞因为包围盒只是实际形状的保守近似。以两个球为例球 A圆心 (0, 0, 0)半径 1 球 B圆心 (1.5, 1.5, 0)半径 1它们的 AABB 在三个轴上都有重叠。但球心距离为[d\sqrt{1.521.52}\approx2.121]而半径之和为[r_Ar_B2]所以两个球实际没有相交。这就是AABB 重叠 ≠ 实际几何相交对于旋转后的细长物体包围盒中的空白区域可能更大误选也更加明显。宽相的设计原则对于需要检测的交互Broad Phase 应尽量做到允许误选包围盒重叠但几何不接触避免漏选应该进一步检测的对象对没有被提交。误选可以由窄相排除漏选则可能导致碰撞丢失。这里的“避免漏选”以正确的边界、更新和配置为前提。只使用离散位置的边界并不能自动避免高速物体穿墙还需要相应的 CCD 机制。四、Narrow Phase把候选对变成接触数据1. 核心职责窄相接收通过宽相和过滤的候选对执行具体几何算法球体 vs 球体 球体 vs 盒体 胶囊 vs 凸体 凸体 vs 凸体 凸体 vs 三角网格对于普通接触其任务不只是返回一个true或false还需要生成求解器所需的接触信息。典型输出包括数据用途接触位置确定接触作用位置及力臂接触法线确定主要约束方向分离距离描述距离或穿透情况接触流形组织一组相关接触几何附加信息支持材质、面索引等后续处理触发器交互则通常只需要重叠状态不进入普通接触冲量求解。2. 不同形状使用不同算法例如球体与球体可以使用简单解析计算凸体之间可能使用 GJK、EPA、SAT 及其他专用路径凸体与网格通常先筛选相关三角形再进行局部检测持续接触可以利用持久接触流形减少重复计算。所以不能把 PhysX 的整个窄相概括为“统一执行一次 GJK”。3. 接触不一定要求已经穿透PhysX 可以根据接触生成参数在几何尚未实际穿透时生成接触。因此更准确的表述是Narrow Phase 判断是否需要生成接触并计算接触数据而不只是判断几何体是否相交。例如两个形状可能已经进入接触生成距离但还没有达到静止时的目标间距。五、两者如何配合以一个箱子落到地面为例第一步更新边界箱子的位置与旋转 ↓ 更新箱子的世界空间 AABB第二步宽相筛选箱子的边界与地面的边界形成候选重叠 ↓ 产生或维持候选对此时只能确认“值得继续检查”。第三步碰撞过滤检查是否允许这两类对象交互是否为触发器是否需要接触响应是否请求通知等。第四步窄相生成接触箱子几何 地面几何 ↓ 计算接触位置、法线和分离距离第五步交给约束求解器接触数据 质量 惯性 速度 材质 ↓ 约束准备与求解 ↓ 计算支撑、摩擦或反弹响应Broad Phase 和 Narrow Phase 都不负责最终决定“把箱子弹多远”。运动响应属于后续约束求解。六、这种拆分究竟节省了什么可以用一个简化成本模型表示[T\approxT_{\text{边界更新}}T_{\text{宽相搜索}}K \cdot C_{\text{窄相}}]其中(K)进入窄相的有效候选对数量(C_{\text{窄相}})平均单对精确检测成本。如果直接两两精确检测[T_{\text{直接}}\approx\frac{N(N-1)}{2}\cdot C_{\text{窄相}}]两阶段设计的关键是在典型场景里让[K \ll \frac{N(N-1)}{2}]不过宽相没有消灭最坏情况。如果大量物体挤在同一个区域所有边界都互相重叠候选对数量仍可能接近 (O(N^2))。不能笼统地说 Broad Phase 把任何场景都变成了 (O(N\log N))。七、PhysX 还会利用“上一物理步”的结果实际引擎不会每步完全从零开始。Broad Phase 的时间相干性维护候选对变化新增重叠对 保持重叠的关系 已经分离的对对于变化较小的场景增量更新比全量重建更有效。Narrow Phase 的时间相干性复用接触缓存和持久接触流形上一物理步的接触 本步的相对运动 ↓ 验证、更新或补充接触例如静止在桌面上的箱子不需要每步把全部几何关系当作第一次见到来处理。八、对应源码应该看哪里以常见 PhysX 4.x/5.x 源码布局为例职责主要阅读位置AABB 管理、Broad Phasesource/lowlevelaabb/几何测试、接触生成、流形source/geomutils/底层碰撞任务与接触处理组织source/lowlevel/交互生命周期与场景控制source/simulationcontroller/接触约束准备与响应求解source/lowleveldynamics/这些职责会跨模块协作不是一个目录严格对应一个串行阶段。另外Scene Query 不等于模拟碰撞的 Broad Phase。射线、Sweep、Overlap 使用自己的查询组织与加速机制虽然也会复用几何算法。总结对比项Broad PhaseNarrow Phase核心问题谁可能碰到谁是否需要接触接触情况如何主要依据包围盒与空间组织具体几何与接触缓存处理范围场景中的大量边界筛选后的有效候选对输出候选对及其变化接触或重叠数据成本特点强调低成本、大规模筛选单对通常更昂贵是否计算最终碰撞响应否否一句话概括Broad Phase 负责不让昂贵的计算浪费在无关对象上Narrow Phase 负责把“可能碰撞”变成可供求解器使用的精确接触信息。