独立单例的碰撞子系统,负责 broadphase 网格划分、narrowphase 碰撞检测、contact 合并、Enter/Stay/Exit 事件分发。ObjManager::UpdateAll 会在 Step 的合适阶段调用 Step(),使 BaseObject::OnCollisionState 收到每帧碰撞通知。
Entry:记录 token、BasePhysics*指针、grid 坐标与 dirty 标志,分为 dynamic/static 两类以支持不同生命周期。grid_使用grid_key(x,y)生成桶,grid_keys_used_用于清理每帧用过的 bucket。world_shapes_、events_、merged_map_/merged_order_、current_pairs_等临时容器用于缓存世界空间形状、合并 manifold 与跟踪当前碰撞对。prev_collision_pairs_记录上一帧 pairs(用于 Exit),“pair key” 基于 token 编码。
events_清理后;若没有动态/静态条目直接返回。- 清空
grid_keys_used_中记录的 bucket,并 resizeworld_shapes_以容纳所有条目。 - 通过
update_entry_in_grid将 dynamic/static 条目遍历一次:若Entry::dirty则从BasePhysics::get_shape()获取本地形状,依据is_world_shape_enabled()决定是否需变换到 world space;之后调用shape_wrapper_to_aabb计算 AABB,将对象加入覆盖的 grid bucket 并记录 grid 坐标,同时在 world_shapes 缓存中保留最终 shape,最后清除 position dirty 标志。 - 对所有动态格子的邻区执行 narrowphase:遍历 candidate pair,调用
shapes_collide_world(内部执行cf_collide后再运行normalize_and_clamp_manifold)获得CF_Manifold;若产生碰撞则填充CollisionEvent(计算distance_a/b便于排序)并推送events_。 events_去重与排序:先以pair_key消除重复,对于 repeat pair 会通过merge_manifold_contact_points维持最多两个不同 contact;随后按照距离排序以便在回调顺序上更稳定。- 遍历
events_生成当前 pairs map,同时调用ObjManager::Instance().IsValid证明 token 有效;用 token-based 的operator[]获取对应BaseObject,再使用orient_manifold让法线朝向接触对象,并依赖current_pairs_与prev_collision_pairs_判断调用OnCollisionState时的Enter/Stay相位。 prev_collision_pairs_中存在但current_pairs_缺失的 pair 将触发BaseObject::OnCollisionState的Exit回调;退出逻辑也验证 token 仍有效。prev_collision_pairs_与current_pairs_交换,循环结束。
Register(token, BasePhysics*)/Unregister(token)支持重复注册(更新指针),使用dynamic_token_map_/static_token_map_跟踪索引。make_key(token)将(index, generation)编码为uint64_t,确保与ObjManagertoken 匹配。
- 若
BasePhysics::is_world_shape_enabled()为 true,则直接使用 world-space 形状;否则 Step 会根据 position/scale/rotation/pivot 计算。 normalize_and_clamp_manifold、merge_manifold_contact_points保证 manifold 数值稳定。COLLISION_DEBUG编译时可打印详细 shape/Exit 信息,world_shapes_与grid_keys_used_等容器在Step内反复复用以减少分配。 -CollisionEvent::distance_a/distance_b记录 penetration 信息,方便后续扩展(e.g. 物理反馈)。