FERRETGame engine over Babylon.js
Ferret

@ferret/physics-explosions

blast waves, craters, fragments and spall from scaled-distance laws.

41 exports · source in packages/physics-explosions/src

Functions

arrivalTime function

function arrivalTime(r: number, tnt: number, curve: BlastCurve = KINNEY_GRAHAM): number

Time the front takes to reach r: the integral of dR / U with the Rankine-Hugoniot shock speed U = c·sqrt(1 + 6 Ps / 7 P0).

packages/physics-explosions/src/blast.ts:47

blastAt function

function blastAt(r: number, tnt: number, curve: BlastCurve = KINNEY_GRAHAM): BlastPoint

The blast at distance r from a charge of tnt kg: the wave is taken as a triangle, so the impulse is Ps·t+/2.

packages/physics-explosions/src/blast.ts:40

blastLoad function

function blastLoad(ps: number, area: number, drag = 1, ambient = P_ATM): number

Force a drag body takes in the blast: (peak overpressure around it, in the diffraction phase) plus drag times dynamic pressure.

packages/physics-explosions/src/blast.ts:154

blastWind function

function blastWind(ps: number, ambient = P_ATM): { speed: number; dynamic: number }

Wind behind the front: speed u = c 5 Ps / (7 P0) / sqrt(1 + 6 Ps / 7 P0) and the dynamic pressure q = 5 Ps^2 / (2 (7 P0 + Ps)) that pushes on what stands in it.

packages/physics-explosions/src/blast.ts:148

craterRadius function

function craterRadius(law: CraterLaw, tnt: number, burial = 0): number

Crater radius for a charge of tnt kg whose centre is buried burial m: the surface-burst scaling times a burial factor.

packages/physics-explosions/src/blast.ts:127

diffracted function

function diffracted(tnt: number, source: number[], edge: number[], target: number[], curve: BlastCurve = KINNEY_GRAHAM): { path: number; turn: number; overpressure: number; arrival: number }

Diffraction around an edge, as a path and a loss: the front reaches a point in the shadow by the way over the edge (path = to the edge + from the edge), so it arrives later and lower than in the open: the pressure is the free-field value at that path length times 1 / (1 + turn / pi x 2), where turn is the angle the way bends at the edge (0 = no shadow). It is an engineering approximation, not a wave solution: it is continuous at the shadow boundary, falls with the bend and with the longer path.

packages/physics-explosions/src/blast.ts:180

ejecta function

function ejecta(craterR: number, mass: number, gravity = 9.81, mu = 0.55, c = 0.5): Ejecta

What a crater throws out (Housen-Holsapple scaling): material leaving at radius r from the centre goes at v = c sqrt(g R) (R / r)^(1/mu), so the mass faster than v is the whole ejected mass x (v / v(R))^(-3 mu) and it lands at v^2 sin(2 angle) / g.

packages/physics-explosions/src/blast.ts:196

explosions function

function explosions(o: ExplosionOptions = {}): ExplosionCapability

packages/physics-explosions/src/index.ts:107

gurneyVelocity function

function gurneyVelocity(casing: number, charge: number, shape: CasingShape = 'cylinder', gurney = TNT_GURNEY): number

Gurney: v = sqrt(2E) / sqrt(M/C + k), with k = 1/2 (cylinder), 3/5 (sphere), 1/3 (open plate, one side).

packages/physics-explosions/src/blast.ts:82

mottMasses function

function mottMasses(total: number, mu: number, rand: () => number, max = 10000): number[]

Mott: masses of fragments with the cumulative number N(m) = (M / 2mu)·exp(-sqrt(m/mu)); so the mean mass is 2·mu and the number M/(2·mu). The masses are drawn as mu·E² with E exponential, then scaled so they add up to M exactly.

packages/physics-explosions/src/blast.ts:97

obliqueReflection function

function obliqueReflection(ps: number, incidence: number, ambient = P_ATM): number

The reflected overpressure at an incidence angle (0 = head on, 90 deg = grazing): the head-on value blends to the incident one with cos^2, a standard engineering fit that Mach reflection beyond about 40 deg only raises.

packages/physics-explosions/src/blast.ts:142

penetrate function

function penetrate(o: { mass: number; speed: number; angle: number; area: number } & Armour & { grazing?: number }): Penetration

What a fragment does to a plate, by its energy against the work of pushing a hole through: the plate resists with its strength over the fragment's presented area along the slant thickness t / cos θ (θ from the plate's normal). Through when the energy is more than that work, with the speed the rest gives; stopped in it otherwise, at the depth the energy reaches; and at a grazing angle (past grazing, 70° by default) a fragment that could not get through the slant skids off: a ricochet.

packages/physics-explosions/src/index.ts:40

radiusFor function

function radiusFor(pressure: number, tnt: number, curve: BlastCurve = KINNEY_GRAHAM): number

The distance at which the peak overpressure falls to pressure (Pa); the radius of a given damage ring.

packages/physics-explosions/src/blast.ts:59

reflectedPressure function

function reflectedPressure(ps: number, ambient = P_ATM): number

Peak pressure on a wall the front meets head on (normal reflection of an ideal gas): Pr = 2Ps (7P0 + 4Ps) / (7P0 + Ps), so 2 Ps for a weak wave and up to 8 Ps for a strong one.

packages/physics-explosions/src/blast.ts:137

rng function

function rng(seed: number)

A seeded generator (mulberry32): the same seed, the same pieces.

packages/physics-explosions/src/blast.ts:88

scaledDistance function

function scaledDistance: (r: number, tnt: number) => number

Hopkinson-Cranz scaled distance, m/kg^(1/3).

packages/physics-explosions/src/blast.ts:35

spall function

function spall(stress: number, duration: number, tensile: number, density: number, waveSpeed: number, wall: number): Spall

Hopkinson spalling: the compression pulse in a wall (peak stress, length duration x wave speed) comes back from the free back face as tension; it tears off a slab where the tension passes tensile, a slab as thick as the length of the pulse's part that exceeds it (at most half the wall), and the slab leaves with the momentum of the pulse above the strength: speed = impulse above it / (rho x slab).

packages/physics-explosions/src/blast.ts:164

underwaterAt function

function underwaterAt(r: number, tnt: number): { overpressure: number; theta: number; impulse: number }

Under water (Cole): the peak pressure and the decay constant of the exponential pulse; the impulse is their product.

packages/physics-explosions/src/blast.ts:67

vesselTnt function

function vesselTnt(pressure: number, volume: number, gamma = 1.4, ambient = P_ATM): number

The charge of a vessel bursting under pressure (Brode): E = (p1 - p0)·V / (gamma - 1), as kg of TNT.

packages/physics-explosions/src/blast.ts:74

Interfaces

Armour interface

interface Armour

A plate a fragment meets: its thickness (m) and the stress (Pa) it resists a projectile with (≈ 3× the tensile strength for steel).

thickness: number
strength: number

packages/physics-explosions/src/index.ts:31

BlastCurve interface

interface BlastCurve
overpressure(z: number): numberpeak incident overpressure, Pa, at scaled distance z (m/kg^(1/3))
duration(z: number): numberpositive-phase duration, s per kg^(1/3)

packages/physics-explosions/src/blast.ts:14

BlastPoint interface

interface BlastPoint
overpressure: number
duration: number
impulse: number
arrival: number
scaled: number

packages/physics-explosions/src/blast.ts:37

Casing interface

interface Casing
mass: number
shape?: CasingShape
mu?: number
density?: number
gurney?: number

packages/physics-explosions/src/index.ts:49

CraterLaw interface

interface CraterLaw
k: numberapparent radius of a surface burst of 1 kg: R = k·W^(1/3.4), m
depthRatio: numberdepth / radius of the apparent crater
camouflet: numberscaled depth of burial (m/kg^(1/3)) at which no crater opens (a camouflet)
throw: numbershare of the heap thrown out beyond the rim

packages/physics-explosions/src/blast.ts:106

DetonateDef interface

interface DetonateDef
at: Vec3
tnt?: numberkg of TNT equivalent, or ...
energy?: number... joules
burst?: BurstKind
burial?: numberdepth of the charge centre under the ground, m
casing?: Casing
seed?: number
vessel?: { pressure: number; volume: number; gamma?: number }a vessel that bursts: {pressure, volume, gamma?} (Brode) in place of tnt

packages/physics-explosions/src/index.ts:50

Ejecta interface

interface Ejecta
velocity: (r: number) => number
massFaster: (v: number) => number
range: (r: number, angle?: number) => number
total: number

packages/physics-explosions/src/blast.ts:191

ExplosionCapability interface

interface ExplosionCapability extends Capability
detonate(def: DetonateDef): ExplosionResult
preview(tnt: number, pressures: number[]): number[]Radii (m) at which the peak overpressure falls to each of the given values (Pa).
setTerrain(t: Terrain | undefined): void
readonly fragments: ReadonlySet<Entity>

packages/physics-explosions/src/index.ts:87

ExplosionOptions interface

interface ExplosionOptions
terrain?: Terrain
curve?: BlastCurve
craters?: Record<string, CraterLaw>
maxFragments?: numberfragments alive at once; the oldest are recycled
perFrame?: numberfragments created per step
fragmentLife?: numberseconds a fragment lives

packages/physics-explosions/src/index.ts:75

ExplosionResult interface

interface ExplosionResult
tnt: number
effective: numbereffective yield after the ground reflection / coupling, kg
bodies: number
fragments: number
crater?: { radius: number; depth: number; removed: number; thrown: number; fallback: number }
camouflet: boolean

packages/physics-explosions/src/index.ts:65

Penetration interface

interface Penetration
outcome: 'through' | 'stopped' | 'ricochet'
depth: number
exitSpeed: number
slant: number

packages/physics-explosions/src/index.ts:32

Spall interface

interface Spall
spalls: boolean
thickness: number
speed: number

packages/physics-explosions/src/blast.ts:158

WallSpec interface

interface WallSpec

A wall that a blast meets: its tensile strength (Pa), density, speed of sound in it and thickness (m); when the reflected pulse tears a slab off the back, explosion:spall follows.

tensile: number
density: number
waveSpeed: number
thickness: number

packages/physics-explosions/src/index.ts:27

Types

BurstKind type

type BurstKind = 'air' | 'surface' | 'buried' | 'water'

packages/physics-explosions/src/index.ts:47

CasingShape type

type CasingShape = 'cylinder' | 'sphere' | 'plate'

packages/physics-explosions/src/blast.ts:79

Constants

EXAMPLE_CRATERS const

const EXAMPLE_CRATERS: Record<string, CraterLaw>

packages/physics-explosions/src/blast.ts:117

EXPLOSION_DEFAULTS const

const EXPLOSION_DEFAULTS: { minPressure: number; rupture: number; area: number | undefined; transmission: number; spread: number; armour: Armour | undefined; wall: WallSpec | undefined; }

packages/physics-explosions/src/index.ts:28

KINNEY_GRAHAM const

const KINNEY_GRAHAM: BlastCurve

packages/physics-explosions/src/blast.ts:21

P_ATM const

const P_ATM: 101325

packages/physics-explosions/src/blast.ts:9

SOUND_SPEED const

const SOUND_SPEED: 340.3

packages/physics-explosions/src/blast.ts:10

TNT_GURNEY const

const TNT_GURNEY: 2440

Gurney constant sqrt(2E) of TNT, m/s

packages/physics-explosions/src/blast.ts:12

TNT_JOULES_PER_KG const

const TNT_JOULES_PER_KG: 4184000

The laws of a blast as plain functions: scaled distance, overpressure, positive-phase duration and impulse, the under-water pulse, Gurney velocity, Mott fragment masses and cratering. Units are SI; yield is in kilograms of TNT equivalent.

The air curve is the Kinney-Graham fit of the free-air burst; it is the data slot a Kingery-Bulmash table can replace (BlastCurve), and every capability function below takes the curve as an argument.

packages/physics-explosions/src/blast.ts:8