Using Matter.Vector.cross for Torque in Matter.js
This article explains how to determine the rotational force, or
torque, generated by an off-center contact in the Matter.js physics
engine using Matter.Vector.cross. In two-dimensional
physics simulations, when a force is applied anywhere other than an
object's center of mass, it induces both linear acceleration and angular
acceleration. By computing the 2D cross product of the lever arm vector
and the applied force vector, you can extract the exact scalar torque
value needed to govern rotational responses.
The Physics of Off-Center Impacts
Rotational force (\(\tau\), or torque) is defined mathematically by the cross product of the displacement vector (\(\mathbf{r}\)) and the force vector (\(\mathbf{F}\)):
\[\tau = \mathbf{r} \times \mathbf{F}\]
- \(\mathbf{r}\) (Lever Arm): The vector pointing from the body's center of mass to the point where the force or contact occurs.
- \(\mathbf{F}\) (Force): The directional vector of the applied force or collision impulse.
In a 2D coordinate system, the cross product between two vectors, \(A(x_1, y_1)\) and \(B(x_2, y_2)\), results in a scalar perpendicular to the 2D plane:
\[\text{cross}(A, B) = (x_1 \cdot y_2) - (y_1 \cdot x_2)\]
A positive result indicates counter-clockwise torque, while a negative result indicates clockwise torque (or vice versa, depending on the coordinate orientation).
How
Matter.Vector.cross Works
The Matter.Vector.cross(vectorA, vectorB) function in
Matter.js executes this precise 2D scalar formula. It takes two objects
containing x and y properties and returns a
single numerical value representing the signed magnitude of the cross
product.
Step-by-Step Implementation
To calculate the torque from an off-center contact, follow these steps:
- Find the Lever Arm Vector: Subtract the body's
center of mass position from the contact point position using
Matter.Vector.sub. - Obtain the Force Vector: Define or extract the force/impulse vector acting on that contact point.
- Compute the Cross Product: Pass the lever arm and
the force vector into
Matter.Vector.cross. - Apply Torque: Assign or accumulate the resulting
scalar directly to the body's
torqueproperty, or apply it as angular momentum.
Code Example
// Assume 'body' is a Matter.Body instance
// Assume 'contactPoint' is a {x, y} coordinate where collision/force occurs
// Assume 'force' is a {x, y} vector representing the applied force
// 1. Calculate the lever arm vector (r) from center of mass to contact point
const leverArm = Matter.Vector.sub(contactPoint, body.position);
// 2. Compute the rotational force (torque) using the 2D cross product
const torque = Matter.Vector.cross(leverArm, force);
// 3. Apply the torque to the body
body.torque += torque;Reading Torque During Collision Events
When handling collision events via
Matter.Events.on(engine, 'collisionStart', callback),
contact points can be retrieved through the collision pairs.
Matter.Events.on(engine, 'collisionStart', (event) => {
event.pairs.forEach((pair) => {
const bodyA = pair.bodyA;
const bodyB = pair.bodyB;
// Retrieve the first active contact point
const contact = pair.collision.supports[0];
if (!contact) return;
// Lever arms for both colliding bodies
const rA = Matter.Vector.sub(contact, bodyA.position);
const rB = Matter.Vector.sub(contact, bodyB.position);
// Approximate collision normal force
const normal = pair.collision.normal;
const impulseMagnitude = pair.collision.penetration; // Used as force proxy
const contactForce = Matter.Vector.mult(normal, impulseMagnitude);
// Calculate rotational tendency on both bodies
const torqueA = Matter.Vector.cross(rA, contactForce);
const torqueB = Matter.Vector.cross(rB, Matter.Vector.neg(contactForce));
});
});Using Matter.Vector.cross directly reveals how much
rotational spin an off-center force contributes to a body, providing
full control over custom angular dynamics and hit reactions in
Matter.js.