Tsunami Wave Runup and Debris Modeling in Matter.js
This article explains how to simulate 2D tsunami wave runup and onshore debris transport using the Matter.js physics engine. By representing water mass as an ensemble of clustered circular rigid bodies—a technique adapted from discrete element methods—developers can approximate complex hydrodynamic phenomena such as shoaling, shoreline inundation, and floating object dynamics directly within a browser environment.
1. Representing Fluid with Clustered Discs
Matter.js is a rigid-body physics engine rather than a continuous
fluid solver. To simulate water, you must discretize the fluid mass into
a large cluster of small, uniform circular bodies
(Matter.Bodies.circle).
For fluid-like behavior, configure the particle properties to minimize shearing resistance while preserving volume:
- Friction and Friction Static: Set both to
0or near-zero to allow particles to slide freely past one another. - Restitution: Keep restitution low (e.g.,
0.0to0.1) to prevent excessive, unphysical bouncing between water discs. - Density: Set an appropriate density (e.g.,
0.001) to ensure water exerts sufficient momentum when colliding with obstacles. - Slop: Reduce the
slopparameter on bodies to minimize overlapping and maintain stable stacking.
2. Setting Up Bathymetry and Coastal Incline
To observe wave shoaling and runup, construct the physical domain
using static composite bodies (isStatic: true):
- Deep Water Basin: A flat, deep channel where the wave initiates.
- Continental Slope/Beach: A series of angled static rectangles or a vertex-based body sloping upward from the seabed past the baseline water level.
- Onshore Plain: A flat or urbanized surface above the water line where debris sits and the wave runs up.
3. Generating the Tsunami Wave
Unlike wind-driven surface waves, a tsunami involves the displacement of an entire water column. You can generate this wave using two primary methods in Matter.js:
- The Piston (Paddle) Generator: Place a static or
kinematic vertical boundary at the rear of the deep basin. Move this
plate forward using
Matter.Body.setVelocityorMatter.Body.setPositionover a specific duration to physically push the particle mass forward. - Localized Impulse: Select a subset of fluid discs
in the deep basin and apply an instantaneous force vector
(
Matter.Body.applyForce) toward the shoreline.
As the dense cluster of discs enters the shallow slope, the narrowing vertical space forces the particles upward and forward, creating shoaling and overland runup.
4. Simulating Buoyancy and Debris Dynamics
Solid debris (shipping containers, vehicles, or structural fragments) can be modeled as dynamic rectangular bodies positioned along the coastline.
Matter.js does not calculate fluid displacement buoyancy out of the box. You can handle debris interaction through two methods:
- Pure Contact Momentum (Simple): If the debris density is calibrated lower than the combined water disc density, the clustered discs will naturally lift and carry the debris via continuous micro-collisions.
- Submergence-Based Buoyancy Forces (Advanced): Use
the
beforeUpdateevent loop to detect when debris overlaps with fluid discs. Count the number of contacting fluid particles usingMatter.Query.collides, and apply a corresponding upward vertical force to the debris center of mass:
Matter.Events.on(engine, 'beforeUpdate', () => {
const overlappingDiscs = Matter.Query.collides(debrisBody, waterDiscs);
const buoyantFactor = 0.0005;
if (overlappingDiscs.length > 0) {
Matter.Body.applyForce(debrisBody, debrisBody.position, {
x: 0,
y: -buoyantFactor * overlappingDiscs.length
});
}
});5. Engine Optimization for Particle Stability
Running hundreds or thousands of rigid discs simultaneously can strain browser performance. Optimize the simulation with the following adjustments:
- Collision Iterations: Increase
engine.positionIterations(e.g., 6 to 8) to prevent fluid particles from tunnelling through the bathymetry or each other during high-velocity impacts. - Broadphase Configuration: Ensure the broadphase algorithm can handle high body counts efficiently. Use Matter.js’s spatial grid or default broadphase without unnecessary object creation per frame.
- Particle Count vs. Radius: Balance visual resolution and frame rate. Larger radii (fewer total particles) run faster, whereas smaller radii capture finer wave-breaking and debris-entrainment behaviors.