How Matter.Axes.rotate Updates Axes in Matter.js
This article provides an overview of how the
Matter.Axes.rotate method updates projection axes for
rotating bodies in Matter.js. It explains the underlying 2D rotation
mathematics, the in-place array mutation used for performance, and the
critical role these updated axes play in rigid body collision detection
via the Separating Axis Theorem (SAT).
The Role of Axes in Matter.js
Matter.js relies on the Separating Axis Theorem (SAT) to detect collisions between convex polygonal bodies. SAT requires projecting the vertices of two shapes onto a set of 1D axes (normal vectors perpendicular to each polygon's edges). If the projections overlap on all axes, a collision occurs.
When a rigid body rotates, the orientation of its edges changes. To keep collision detection accurate without recalculating normal vectors from scratch every frame, Matter.js stores normalized axis vectors on the body and rotates them dynamically to match the body's angular displacement.
The Mathematical Transformation
The Matter.Axes.rotate method takes an array of axis
vectors and an angle \(\theta\) (in
radians). It applies a standard 2D rotation matrix to each vector in the
collection:
\[\begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} \cos(\theta) & -\sin(\theta) \\ \sin(\theta) & \cos(\theta) \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix}\]
In code, this operation is executed as follows:
- Precompute Trigonometry: The function calculates
Math.cos(angle)andMath.sin(angle)once per call, minimizing redundant trigonometric operations across the axis array. - Transform Coordinates: For each axis vector \((x, y)\), the new coordinates are computed:
- \(x_{new} = x \cdot \cos(\theta) - y \cdot \sin(\theta)\)
- \(y_{new} = x \cdot \sin(\theta) + y \cdot \cos(\theta)\)
- In-Place Mutation: The function directly assigns
the new values back to the axis object properties
(
axis.x = x_newandaxis.y = y_new).
Because pure rotation preserves vector magnitude, the normalized unit length of each axis vector remains unchanged, eliminating the need for an expensive square root normalization step after rotation.
Execution Within the Body Update Lifecycle
Matter.Axes.rotate is typically invoked during calls to
Matter.Body.rotate or when angular velocity is integrated
during the engine's update cycle.
- Trigger: An angular change \(\Delta\theta\) is applied to a body.
- Vertices Update: The body's actual vertices are
rotated around its center of mass using
Matter.Vertices.rotate. - Axes Update:
Matter.Axes.rotate(body.axes, angle)is executed immediately to align the normal vectors with the new edge orientations. - Collision Pipeline: The updated axes are
subsequently queried by
Matter.DetectorandMatter.SATto perform broadphase and narrowphase collision checks against other bodies in world space.
By rotating pre-existing vectors in-place rather than allocating new
objects, Matter.Axes.rotate avoids garbage collection
overhead, ensuring steady frame rates during complex multi-body
simulations.