How Matter.Vertices.area Calculates Mass in Matter.js
In Matter.js, the mass of a custom convex body is fundamentally
linked to its two-dimensional geometry through the formula
mass = density * area. The
Matter.Vertices.area function plays a critical role by
calculating the exact geometric surface area of a polygon from its
defining coordinate points. This article explains how Matter.js uses
this function during body generation, how it ensures realistic mass and
rotational inertia distribution for custom shapes, and what developers
need to know about the engine's underlying area calculations.
The Relationship Between Area, Density, and Mass
Matter.js is a two-dimensional rigid-body physics engine. Because bodies do not have depth or volume, mass cannot be calculated using volumetric density. Instead, the engine represents mass proportionally through two-dimensional areal density:
\[\text{Mass} = \text{Density} \times \text{Area}\]
When you create standard geometric primitives such as rectangles or
circles using factory methods like Matter.Bodies.rectangle
or Matter.Bodies.circle, the engine calculates their areas
using standard closed-form equations (\(w
\times h\) or \(\pi r^2\)).
However, for custom convex polygons defined by an arbitrary set of
points, no single geometric formula applies. This is where
Matter.Vertices.area becomes necessary.
How
Matter.Vertices.area Operates
The Matter.Vertices.area(vertices, signed) method takes
an array of vertex objects (each containing x and
y coordinates) and computes the total area of the closed
polygon.
Under the hood, this function implements the Shoelace formula (also known as Gauss's area formula). It traverses the perimeter of the polygon, calculating the determinant of adjacent coordinate pairs:
\[A = \frac{1}{2} \left| \sum_{i=0}^{n-1} (x_i y_{i+1} - x_{i+1} y_i) \right|\]
Key behaviors of this function include:
- Signed vs. Unsigned Output: By default, or when
signedis set tofalse, the function returns the absolute (positive) area. Ifsignedistrue, the sign indicates the winding order (clockwise versus counter-clockwise) of the vertices. - Vertex Ordering: The algorithm assumes the vertices are passed in sequential order along the perimeter of the convex hull.
The Initialization Pipeline for Custom Convex Bodies
When a custom body is created using
Matter.Bodies.fromVertices or
Matter.Body.create, the engine executes a specific
initialization sequence:
- Vertex Validation and Convex Hull Processing: The input points are normalized, validated, and ensured to form a convex shape (or decomposed into convex sub-parts if the original shape is concave).
- Area Calculation: The engine invokes
Matter.Vertices.areaon the processed vertices. - Mass Computation: Using the default density
(
0.001unless explicitly overridden), the body sets itsmassproperty equal to the calculated area multiplied by that density. - Inverse Mass: The engine automatically calculates
inverseMass = 1 / mass, which is used across all constraint and collision impulse solvers to improve performance.
Impact on Rotational Inertia
Matter.Vertices.area indirectly impacts how a custom
body rotates. Along with mass, custom convex bodies require an accurate
moment of inertia (body.inertia).
Matter.js computes the inertia of a polygon by summing the second moments of area across its triangular sub-segments relative to the body's centroid. Because the total mass is distributed across the calculated area, any inaccuracy in the vertex area calculation would distort the body's resistance to angular acceleration, causing unnatural rotations during collisions and joint constraints.
Overriding Default Behavior
While Matter.Vertices.area handles mass automation
reliably, developers can override the resulting mass at or after
instantiation:
- Explicit Mass: Setting
{ mass: 50 }in the body's definition options bypasses the density-area calculation, forcing the specified mass while internally scaling thedensityproperty to match the computed area. - Explicit Density: Setting a custom
densityallowsMatter.Vertices.areato scale the mass naturally with the size of the shape, preserving dynamic realism when bodies are scaled at runtime viaMatter.Body.scale.