How does planck.js manage broad-phase collisions?
Planck.js efficiently manages internal broad-phase collision detection by utilizing a dynamic AABB (Axis-Aligned Bounding Box) tree structure to minimize the number of expensive narrow-phase shape checks. As a 2D rigid-body physics engine ported from Box2D, Planck.js isolates the spatial queries of a high volume of moving bodies into a lightweight proxy system. This architecture replaces computationally heavy \(O(N^2)\) brute-force pair comparisons with optimized, tree-traversal algorithms that quickly filter out shapes that are nowhere near each other.
The Role of the Dynamic Tree
At the core of the broad-phase management in Planck.js is the
DynamicTree class. This internal structure organizes shapes
based on their AABBs rather than their actual complex geometry (such as
polygons or edge chains).
- Leaf Nodes and Proxies: When a fixture is created on a physics body, the broad-phase system allocates a “proxy” for it inside the dynamic tree. Each leaf node in the tree corresponds to one of these proxies and holds a pointer to the user data or fixture.
- AABB Fattening: To prevent the tree from needing constant recalculations when objects move minor distances, Planck.js “fattens” the bounding boxes by a small buffer margin. It also extends the AABB along the body’s velocity vector to predict its movement. If a body moves within its fattened AABB, the tree structure does not need to be updated, saving significant CPU cycles.
The Pair Management Pipeline
The broad-phase layer does not permanently track ongoing collisions; instead, its primary goal is to surface a list of potentially overlapping pairs for the narrow-phase solver. This is handled through a structured lifecycle during each physics time step:
- Proxy Movement: When a body moves significantly
enough to breach its fattened bounding box, the internal
MoveProxymethod is executed. The proxy’s AABB is updated, and the node is re-inserted into the tree. - Flagging for Review: Moved proxies are placed into an internal buffer of changed nodes.
- Querying the Tree: During the synchronizing phase, Planck.js iterates through this buffer. For every moved proxy, it performs an AABB query against the rest of the dynamic tree to find overlapping leaf nodes.
- Generating Collision Pairs: If the query detects overlapping bounding boxes between two distinct proxies, the broad-phase creates or updates a “collision pair” and hands it off to the contact manager.
Optimizing Ray Casts and Region Queries
Beyond basic pair generation, the internal broad-phase setup exposes
fast spatial optimization hooks for developers. Because the
DynamicTree structure maintains hierarchical bounding
boxes, ray casting or region querying through the World
class can bypass massive subsets of data. Instead of testing a line or
region against every single object in the simulation, the algorithm
skips entire branches of the tree if the ray or box does not intersect
the parent node’s bounding envelope.