Skip to content

@gameable/physics-jolt ​

Interfaces ​

BodyArgs ​

Everything needed to create one body. Mirrors the WIT add-body command, minus the entity handle, which the host module owns.

Properties ​

angularDamping? ​
ts
optional angularDamping?: number;

Angular velocity damping per second. Defaults to 0.05.

dims ​
ts
dims: readonly number[];

Shape dimensions, in metres: box half-extents [hx, hy, hz]; sphere [radius]; capsule and cylinder [radius, halfHeight]. Ignored for mesh and convex.

flags? ​
ts
optional flags?: BodyFlags;

Optional switches.

friction ​
ts
friction: number;

Coulomb friction, 0..1.

geometry? ​
ts
optional geometry?: Shape;

Prebuilt shape for mesh and convex bodies, from meshShapeFromGeometry or convexHullFromPoints. The world takes its own reference, so one shape can back many bodies.

id ​
ts
id: number;

Guest-minted handle. Must not already exist in this world.

kind ​
ts
kind: BodyKind;

Body class.

layer ​
ts
layer: number;

What this body is, as a bitset.

linearDamping? ​
ts
optional linearDamping?: number;

Linear velocity damping per second. Defaults to 0.05, Jolt's own default.

mask ​
ts
mask: number;

What this body collides with, as a bitset of other bodies' layers.

mass ​
ts
mass: number;

Kilograms. Ignored for static, kinematic and character bodies.

position ​
ts
position: Vec3;

World-space position of the body origin.

restitution ​
ts
restitution: number;

Bounciness, 0..1.

rotation ​
ts
rotation: Quat;

World-space orientation, xyzw.

shape ​
ts
shape: ShapeKind;

Shape family. mesh and convex additionally need BodyArgs.geometry.


BodyFlags ​

Per-body switches. Mirrors WIT body-flags.

Properties ​

asleep? ​
ts
optional asleep?: boolean;

Start the body asleep: it stays exactly where it is put, costing nothing, until something touches it or a command moves it. For things laid out by hand or by a maker (a made world's loose things), which should be found as they were placed rather than settle a few centimetres on the first step.

ccd? ​
ts
optional ccd?: boolean;

Use continuous collision detection (linear cast).

lockRotation? ​
ts
optional lockRotation?: boolean;

Lock all rotation. The usual choice for a capsule.

noSleep? ​
ts
optional noSleep?: boolean;

Never let the solver put this body to sleep.

reportContacts? ​
ts
optional reportContacts?: boolean;

Emit this body's contacts from PhysicsWorld.drainContacts.

Off by default. A world of resting crates generates a manifold per touching pair per step whether or not anyone reads it, and turning those into records costs a wasm crossing each. Ask for contacts on the handful of bodies whose collisions the game reacts to — the player, projectiles, triggers — and the rest cost nothing at all.

reportStay? ​
ts
optional reportStay?: boolean;

Also emit the stay phase, once per step for as long as the pair touches.

Off by default, and only meaningful together with BodyFlags.reportContacts: begin and end are edges, so a game that tracks "am I touching this" needs no more than those two. stay is the expensive one — a box resting on the floor emits it sixty times a second forever — so it is separately opt-in, for the rare system that wants a live contact point (a grinding-sparks effect, a pressure plate that weighs what is on it).

sensor? ​
ts
optional sensor?: boolean;

Trigger volume: generates contacts but no collision response.


ContactRecord ​

One contact event. Instances are pooled by the world and by the caller's out array; copy anything you want to keep past the next drainContacts.

Properties ​

a ​
ts
a: number;

Guest body id of the first body.

b ​
ts
b: number;

Guest body id of the second body.

impulse ​
ts
impulse: number;

Estimated normal impulse, newton-seconds. Jolt does not hand the solved impulse to a contact listener, so this is reduced mass * closing speed measured before the solve: right in order of magnitude, good enough to scale an impact sound, not a physical measurement.

nx ​
ts
nx: number;

Contact normal pointing from a towards b, x. Zero for end.

ny ​
ts
ny: number;

Contact normal, y.

nz ​
ts
nz: number;

Contact normal, z.

phase ​
ts
phase: ContactPhase;

Whether the contact started, continued or ended.

px ​
ts
px: number;

World-space contact point, x. Zero for end.

py ​
ts
py: number;

World-space contact point, y. Zero for end.

pz ​
ts
pz: number;

World-space contact point, z. Zero for end.


ConvexHullOptions ​

Options for convexHullFromPoints.

Properties ​

centreOfMassOffset? ​
ts
optional centreOfMassOffset?: readonly [number, number, number];

Move the shape's centre of mass by this much, metres, in the shape's own frame: a vehicle's weight sits low, well under the middle of its outline.

hullTolerance? ​
ts
optional hullTolerance?: number;

Distance, in metres, below which the hull builder merges coplanar faces.

maxConvexRadius? ​
ts
optional maxConvexRadius?: number;

Maximum convex radius used to round the hull off.


LayerOptions ​

Tuning for the object-layer slot table.

Properties ​

maxObjectLayers? ​
ts
optional maxObjectLayers?: number;

How many distinct Jolt object layers the world may hand out. Half of them back static bodies and half back moving bodies, so the default of 64 allows 32 distinct (layer, mask) pairs on each side.


LoadJoltOptions ​

Options for loadJolt.

Extended by ​

Properties ​

wasmUrl? ​
ts
optional wasmUrl?: string;

Where jolt-physics.wasm.wasm is served from.

Omit it and the loader asks the host for jolt-physics/jolt-physics.wasm.wasm via import.meta.resolve, which is correct under node and under any bundler that keeps an import map. In a plain browser build, pass the URL your bundler minted for the asset:

ts
import wasmUrl from 'jolt-physics/jolt-physics.wasm.wasm?url';

MeshShapeOptions ​

Options shared by the geometry shape builders.

Properties ​

maxTrianglesPerLeaf? ​
ts
optional maxTrianglesPerLeaf?: number;

Triangles per BVH leaf. Higher builds faster and uses less memory, lower queries faster. Jolt's own default is 8.


Monowheel ​

A monowheel in the world. It is driven and read as a Motorcycle is (one wheel's numbers instead of two), so whatever drives a motorbike drives it.

Extends ​

Properties ​

awake ​
ts
readonly awake: boolean;

False while the body sleeps: nothing about the wheels changes until something wakes it.

Inherited from ​

Motorcycle.awake

balanced ​
ts
balanced: boolean;

Held upright by its rider (true, the default): it leans into a turn and stands at rest. False: nobody aboard, nothing holds it, and it falls over and slides as a machine does.

Inherited from ​

Motorcycle.balanced

lean ​
ts
readonly lean: number;

How far it leans now, radians: to its right is positive.

pitch ​
ts
readonly pitch: number;

How far its frame is swung now, radians: nose down is positive.

speed ​
ts
readonly speed: number;

Metres a second along the bike's own forward.

Inherited from ​

Motorcycle.speed

topSpeed ​
ts
topSpeed: number;

The speed the bike is held at under throttle, metres a second (half of it backing up).

Inherited from ​

Motorcycle.topSpeed

Methods ​

dispose() ​
ts
dispose(): void;

Take the wheels and the engine off the body; the body stays.

Returns ​

void

Inherited from ​

Motorcycle.dispose

drive() ​
ts
drive(
   forward, 
   right, 
   brake
): void;

What the rider asks: forward from -1 (back) to 1, right from -1 (left) to 1, brake from 0 to 1. Held until the next call.

Parameters ​
ParameterTypeDescription
forwardnumberThrottle; negative backs up once the bike has stopped.
rightnumberSteering to the right.
brakenumberBoth brakes.
Returns ​

void

Inherited from ​

Motorcycle.drive

read() ​
ts
read(out): void;

The wheels after the last step, front then rear, four numbers each: how far the axle has risen from rest (metres, up positive), how far the wheel is steered (radians, right-handed about up: to the left positive), how far it has turned (radians, rolling forward positive), and 1 when it is on the ground.

Parameters ​
ParameterTypeDescription
outFloat32ArrayAt least 2 * MOTORCYCLE_WHEEL_STRIDE long.
Returns ​

void

Inherited from ​

Motorcycle.read


MonowheelSpec ​

What PhysicsWorld.createMonowheel is asked.

Properties ​

body ​
ts
readonly body: number;

The body the thing is: dynamic, already in the world, its shape clear of the ground.

layer ​
ts
readonly layer: number;

The layer the wheel's cast is made as.

lean? ​
ts
readonly optional lean?: number;

How far it leans into a turn at most, radians. Default MONOWHEEL.lean, 47 degrees.

mask ​
ts
readonly mask: number;

What the wheel rolls on: the collision mask of the cast.

topSpeed? ​
ts
readonly optional topSpeed?: number;

The speed it is held at under throttle, metres a second. Default 14.

torque? ​
ts
readonly optional torque?: number;

The engine's most torque, newton metres. Default 220.

turn? ​
ts
readonly optional turn?: number;

How fast it turns about its own up at most, radians a second. Default 1.5.

wheel ​
ts
readonly wheel: MonowheelWheel;

Its one wheel.


MonowheelWheel ​

The one wheel of a MonowheelSpec. Metres, in the body's own frame.

Properties ​

axle ​
ts
readonly axle: readonly [number, number, number];

Where the ring's middle is with the thing at rest, from the body's origin.

brake ​
ts
readonly brake: number;

The most the brake holds, newton metres.

damping? ​
ts
readonly optional damping?: number;

How fast it settles: 0 never, 1 at once without overshoot. Default 0.7.

down ​
ts
readonly down: number;

How far it lets the body rise from rest before the wheel leaves the ground.

frequency? ​
ts
readonly optional frequency?: number;

How quick the tyre's give is, hertz. Default 4.

radius ​
ts
readonly radius: number;

The tyre's radius.

up ​
ts
readonly up: number;

How far the tyre gives upward from rest.

width ​
ts
readonly width: number;

The tyre's width.


Motorcycle ​

A motorbike in the world.

Extended by ​

Properties ​

awake ​
ts
readonly awake: boolean;

False while the body sleeps: nothing about the wheels changes until something wakes it.

balanced ​
ts
balanced: boolean;

Held upright by its rider (true, the default): it leans into a turn and stands at rest. False: nobody aboard, nothing holds it, and it falls over and slides as a machine does.

speed ​
ts
readonly speed: number;

Metres a second along the bike's own forward.

topSpeed ​
ts
topSpeed: number;

The speed the bike is held at under throttle, metres a second (half of it backing up).

Methods ​

dispose() ​
ts
dispose(): void;

Take the wheels and the engine off the body; the body stays.

Returns ​

void

drive() ​
ts
drive(
   forward, 
   right, 
   brake
): void;

What the rider asks: forward from -1 (back) to 1, right from -1 (left) to 1, brake from 0 to 1. Held until the next call.

Parameters ​
ParameterTypeDescription
forwardnumberThrottle; negative backs up once the bike has stopped.
rightnumberSteering to the right.
brakenumberBoth brakes.
Returns ​

void

read() ​
ts
read(out): void;

The wheels after the last step, front then rear, four numbers each: how far the axle has risen from rest (metres, up positive), how far the wheel is steered (radians, right-handed about up: to the left positive), how far it has turned (radians, rolling forward positive), and 1 when it is on the ground.

Parameters ​
ParameterTypeDescription
outFloat32ArrayAt least 2 * MOTORCYCLE_WHEEL_STRIDE long.
Returns ​

void


MotorcycleSpec ​

What PhysicsWorld.createMotorcycle is asked.

Properties ​

body ​
ts
readonly body: number;

The body the bike is: dynamic, already in the world, its shape clear of the ground.

layer ​
ts
readonly layer: number;

The layer the wheels' casts are made as.

lean? ​
ts
readonly optional lean?: number;

How far the bike leans into a turn at most, radians. Default 45 degrees.

mask ​
ts
readonly mask: number;

What the wheels roll on: the collision mask of the casts.

topSpeed? ​
ts
readonly optional topSpeed?: number;

The speed the bike is held at under throttle, metres a second. Default 14.

torque? ​
ts
readonly optional torque?: number;

The engine's most torque, newton metres. Default 150.

wheels ​
ts
readonly wheels: readonly [MotorcycleWheel, MotorcycleWheel];

The front wheel, then the rear.


MotorcycleWheel ​

One wheel of a MotorcycleSpec. Metres and radians, in the body's own frame.

Properties ​

axle ​
ts
readonly axle: readonly [number, number, number];

Where the axle's middle is with the bike at rest, from the body's origin.

brake ​
ts
readonly brake: number;

The most the brake holds, newton metres.

damping? ​
ts
readonly optional damping?: number;

How fast the springing settles: 0 never, 1 at once without overshoot. Default 0.6.

down ​
ts
readonly down: number;

How far the axle may sink from rest (the springing opens).

driven ​
ts
readonly driven: boolean;

True for the wheel the engine drives.

frequency? ​
ts
readonly optional frequency?: number;

How quick the springing is, hertz. Default 2.

radius ​
ts
readonly radius: number;

The tyre's radius.

steer ​
ts
readonly steer: number;

How far the wheel steers each way, radians; 0 for a wheel that does not steer.

up ​
ts
readonly up: number;

How far the axle may rise from rest (the springing closes).

width ​
ts
readonly width: number;

The tyre's width.


PhysicsOptions ​

Options for physics.

Extends ​

Properties ​

characterStepUp? ​
ts
optional characterStepUp?: number;

How high a step a walking character body climbs without jumping, in metres. Defaults to 0.4, a tall stair. A world whose collision is rough (a made place, where a chest is a lump the walker would otherwise walk up like a stair) wants less: 0.2 keeps the walker on the floor.

Inherited from ​

PhysicsWorldOptions.characterStepUp

characterStrength? ​
ts
optional characterStrength?: number;

The most force a walking character body puts on a body it walks into, in newtons. Defaults to 100, Jolt's own: enough to slide a 5 kg box, and it stops dead at a 20 kg trunk. A person leaning in manages a few hundred; a game whose walker should shove furniture about sets 400 or so.

Inherited from ​

PhysicsWorldOptions.characterStrength

gravity? ​
ts
optional gravity?: Vec3;

Gravity in metres per second squared. Defaults to [0, -9.81, 0].

Inherited from ​

PhysicsWorldOptions.gravity

layers? ​
ts
optional layers?: LayerOptions;

Object-layer slot tuning. See LayerOptions.

Inherited from ​

PhysicsWorldOptions.layers

maxBodies? ​
ts
optional maxBodies?: number;

Hard ceiling on simultaneous bodies. Defaults to 4096.

Inherited from ​

PhysicsWorldOptions.maxBodies

maxBodyPairs? ​
ts
optional maxBodyPairs?: number;

Maximum body pairs the broad phase tracks. Defaults to maxBodies * 2.

Inherited from ​

PhysicsWorldOptions.maxBodyPairs

maxContactConstraints? ​
ts
optional maxContactConstraints?: number;

Maximum contact constraints per step. Defaults to maxBodies.

Inherited from ​

PhysicsWorldOptions.maxContactConstraints

maxContactsPerStep? ​
ts
optional maxContactsPerStep?: number;

Contact records the world keeps for one step. Defaults to 256.

The pool is allocated up front and never grows, because growing it would allocate inside Jolt's own Step(). A step that produces more reportable contacts than this drops the surplus and warns once — raise the ceiling if the game really does want that many in a single step.

Inherited from ​

PhysicsWorldOptions.maxContactsPerStep

substeps? ​
ts
optional substeps?: number;

Collision steps per fixed step. One is right for a 60 Hz simulation; raise it only if fast bodies tunnel and flags.ccd was not enough.

wasmUrl? ​
ts
optional wasmUrl?: string;

Where jolt-physics.wasm.wasm is served from.

Omit it and the loader asks the host for jolt-physics/jolt-physics.wasm.wasm via import.meta.resolve, which is correct under node and under any bundler that keeps an import map. In a plain browser build, pass the URL your bundler minted for the asset:

ts
import wasmUrl from 'jolt-physics/jolt-physics.wasm.wasm?url';
Inherited from ​

LoadJoltOptions.wasmUrl


PhysicsService ​

The physics service, published by the engine under the id physics.

It is the PhysicsWorld plus the debug view, so engine.get('physics').raycast(...) works directly.

Extends ​

Properties ​

bodyCount ​
ts
readonly bodyCount: number;

Number of bodies currently in the world.

Inherited from ​

PhysicsWorld.bodyCount

movingBodyCount ​
ts
readonly movingBodyCount: number;

Rows PhysicsWorld.readBodies would write: the non-static, enabled bodies. Size the destination from this and readBodies never has to be called twice.

Inherited from ​

PhysicsWorld.movingBodyCount

revision ​
ts
readonly revision: number;

Bumped whenever the set of bodies changes: add, remove or enable/disable. Debug views rebuild their geometry when this moves and not otherwise.

Inherited from ​

PhysicsWorld.revision

Methods ​

addBody() ​
ts
addBody(args): void;

Create a body. See BodyArgs.

Parameters ​
ParameterType
argsBodyArgs
Returns ​

void

Inherited from ​

PhysicsWorld.addBody

applyImpulse() ​
ts
applyImpulse(
   id, 
   impulse, 
   point?
): void;

Apply an impulse, at the centre of mass unless point says otherwise.

Parameters ​
ParameterType
idnumber
impulseVec3
point?Vec3
Returns ​

void

Inherited from ​

PhysicsWorld.applyImpulse

bodyIds() ​
ts
bodyIds(): readonly number[];

Snapshot of the live body ids, cheap and non-allocating to iterate.

Returns ​

readonly number[]

Inherited from ​

PhysicsWorld.bodyIds

createMonowheel() ​
ts
createMonowheel(spec): Monowheel;

Make a body that is already in the world a monowheel: one wheel under its middle, an engine, and a balance of its own (level front to back, leaning to steer, upright at rest). It is driven and read as a motorbike is. See Monowheel.

Parameters ​
ParameterType
specMonowheelSpec
Returns ​

Monowheel

Inherited from ​

PhysicsWorld.createMonowheel

createMotorcycle() ​
ts
createMotorcycle(spec): Motorcycle;

Make a body that is already in the world a motorbike: two wheels on springs, an engine, and Jolt's own motorcycle controller, which leans it into a turn and holds it upright at rest. See Motorcycle.

Parameters ​
ParameterType
specMotorcycleSpec
Returns ​

Motorcycle

Inherited from ​

PhysicsWorld.createMotorcycle

createRagdoll() ​
ts
createRagdoll(spec): Ragdoll;

A character's parts as bodies joined by swing-twist joints, in this world: they fall onto whatever the world holds. See Ragdoll.

While any ragdoll has a part the physics leads and awake, every step runs RAGDOLL_STEPS collision steps with the ragdolls' flesh before each.

Parameters ​
ParameterType
specRagdollSpec
Returns ​

Ragdoll

Inherited from ​

PhysicsWorld.createRagdoll

debugWireframe() ​
ts
debugWireframe(scene): void;

Attach or detach a wireframe debug view.

Pass a scene to attach, null to detach and free the geometry. The line buffer is rebuilt only when the set of bodies changes; the per-frame cost is a transform of the cached corners in update, with no allocation.

Parameters ​
ParameterTypeDescription
sceneScene<Object3DEventMap> | nullThe scene to draw into, or null to remove the view.
Returns ​

void

dispose() ​
ts
dispose(): void;

Free every Jolt object this world owns.

Returns ​

void

Inherited from ​

PhysicsWorld.dispose

drainContacts() ​
ts
drainContacts(out): number;

Move queued contacts into out.

Parameters ​
ParameterType
outContactRecord[]
Returns ​

number

Inherited from ​

PhysicsWorld.drainContacts

groundState() ​
ts
groundState(id): GroundState;

What a character body is standing on, as of the last step.

Parameters ​
ParameterType
idnumber
Returns ​

GroundState

Inherited from ​

PhysicsWorld.groundState

isAwake() ​
ts
isAwake(id): boolean;

Whether the physics has a body awake: moving, or not yet come to rest. Unknown ids, static bodies and bodies taken out read false; a character is never asleep and reads true.

Parameters ​
ParameterType
idnumber
Returns ​

boolean

Inherited from ​

PhysicsWorld.isAwake

moveCharacter() ​
ts
moveCharacter(id, desiredVelocity): void;

Set the desired world-space velocity of a character body for the next step.

Parameters ​
ParameterType
idnumber
desiredVelocityVec3
Returns ​

void

Inherited from ​

PhysicsWorld.moveCharacter

overlapSphere() ​
ts
overlapSphere(
   center, 
   radius, 
   mask
): number[];

Guest body ids overlapping a sphere, nearest first.

Parameters ​
ParameterType
centerVec3
radiusnumber
masknumber
Returns ​

number[]

Inherited from ​

PhysicsWorld.overlapSphere

overlapSphereInto() ​
ts
overlapSphereInto(
   center, 
   radius, 
   mask, 
   out
): number;

Zero-allocation form of PhysicsWorld.overlapSphere.

Parameters ​
ParameterType
centerVec3
radiusnumber
masknumber
outUint32Array
Returns ​

number

Inherited from ​

PhysicsWorld.overlapSphereInto

ragdollPartOf() ​
ts
ragdollPartOf(id): 
  | {
  part: number;
  ragdoll: Ragdoll;
}
  | null;

Which ragdoll and part a query's body id names, or null for an ordinary body.

Parameters ​
ParameterType
idnumber
Returns ​

| { part: number; ragdoll: Ragdoll; } | null

Inherited from ​

PhysicsWorld.ragdollPartOf

raycast() ​
ts
raycast(
   origin, 
   direction, 
   maxDistance, 
   mask
): RayHit | null;

Closest hit along a ray, or null. The returned object is reused.

Parameters ​
ParameterType
originVec3
directionVec3
maxDistancenumber
masknumber
Returns ​

RayHit | null

Inherited from ​

PhysicsWorld.raycast

raycastBatch() ​
ts
raycastBatch(
   rays, 
   mask, 
   out
): number;

Many rays, one call.

Parameters ​
ParameterType
raysFloat32Array
masknumber
outFloat32Array
Returns ​

number

Inherited from ​

PhysicsWorld.raycastBatch

readBodies() ​
ts
readBodies(out): number;

Write stride-15 body rows into out. See PhysicsWorld.readBodies.

Parameters ​
ParameterType
outFloat32Array
Returns ​

number

Inherited from ​

PhysicsWorld.readBodies

readBodyBounds() ​
ts
readBodyBounds(
   id, 
   out, 
   offset
): boolean;

Local-space bounds and world transform of a body, for debug drawing.

Parameters ​
ParameterType
idnumber
outFloat32Array
offsetnumber
Returns ​

boolean

Inherited from ​

PhysicsWorld.readBodyBounds

readBodyPose() ​
ts
readBodyPose(
   id, 
   out, 
   offset
): boolean;

World transform of a body alone, when its bounds are already known.

Parameters ​
ParameterType
idnumber
outFloat32Array
offsetnumber
Returns ​

boolean

Inherited from ​

PhysicsWorld.readBodyPose

removeBody() ​
ts
removeBody(id): void;

Destroy a body and release its shape reference. Unknown ids are ignored.

Parameters ​
ParameterType
idnumber
Returns ​

void

Inherited from ​

PhysicsWorld.removeBody

setEnabled() ​
ts
setEnabled(id, enabled): void;

Take a body out of the simulation without destroying it, or put it back.

Parameters ​
ParameterType
idnumber
enabledboolean
Returns ​

void

Inherited from ​

PhysicsWorld.setEnabled

setTransform() ​
ts
setTransform(
   id, 
   position, 
   rotation, 
   teleport?
): void;

Teleport a body. Velocities are left alone unless teleport says otherwise.

Parameters ​
ParameterTypeDescription
idnumberGuest body handle.
positionVec3New world-space position.
rotationQuatNew world-space orientation, xyzw.
teleport?booleanTrue for a hard cut: the body's linear and angular velocities are zeroed too, and a character forgets the velocity it was asked for. False (the default) moves the body and lets it keep moving.
Returns ​

void

Inherited from ​

PhysicsWorld.setTransform

setVelocity() ​
ts
setVelocity(
   id, 
   linear, 
   angular
): void;

Set linear and angular velocity.

Parameters ​
ParameterType
idnumber
linearVec3
angularVec3
Returns ​

void

Inherited from ​

PhysicsWorld.setVelocity

sleep() ​
ts
sleep(id): void;

Put a body to sleep where it is: it stays exactly there, costing nothing, until something touches it or a command moves it. Unknown ids, static bodies and characters are left alone.

Parameters ​
ParameterType
idnumber
Returns ​

void

Inherited from ​

PhysicsWorld.sleep

step() ​
ts
step(dt, substeps?): number;

Advance the simulation.

Parameters ​
ParameterType
dtnumber
substeps?number
Returns ​

number

Inherited from ​

PhysicsWorld.step


PhysicsSteppedEvent ​

What physics:stepped carries.

The object is reused, so a listener must read it and not retain it — the event fires inside fixedUpdate and allocating one of these per step is the thing the whole phase is about.

Example ​

ts
import type { PhysicsSteppedEvent } from 'gameable/physics';

let rows = 0;
engine.events.on('physics:stepped', (e: PhysicsSteppedEvent) => {
  rows = e.movingBodyCount; // read it now; the object is rewritten next step
});

Properties ​

contacts ​
ts
contacts: number;

Contact events this step queued for drainContacts.

dt ​
ts
dt: number;

Length of the step that just ran, in seconds.

movingBodyCount ​
ts
movingBodyCount: number;

Rows the next PhysicsService.readBodies will fill.


PhysicsWorld ​

A live Jolt simulation. Everything the engine's physics command stream and synchronous query imports need, and nothing else.

Extended by ​

Properties ​

bodyCount ​
ts
readonly bodyCount: number;

Number of bodies currently in the world.

movingBodyCount ​
ts
readonly movingBodyCount: number;

Rows PhysicsWorld.readBodies would write: the non-static, enabled bodies. Size the destination from this and readBodies never has to be called twice.

revision ​
ts
readonly revision: number;

Bumped whenever the set of bodies changes: add, remove or enable/disable. Debug views rebuild their geometry when this moves and not otherwise.

Methods ​

addBody() ​
ts
addBody(args): void;

Create a body. See BodyArgs.

Parameters ​
ParameterType
argsBodyArgs
Returns ​

void

applyImpulse() ​
ts
applyImpulse(
   id, 
   impulse, 
   point?
): void;

Apply an impulse, at the centre of mass unless point says otherwise.

Parameters ​
ParameterType
idnumber
impulseVec3
point?Vec3
Returns ​

void

bodyIds() ​
ts
bodyIds(): readonly number[];

Snapshot of the live body ids, cheap and non-allocating to iterate.

Returns ​

readonly number[]

createMonowheel() ​
ts
createMonowheel(spec): Monowheel;

Make a body that is already in the world a monowheel: one wheel under its middle, an engine, and a balance of its own (level front to back, leaning to steer, upright at rest). It is driven and read as a motorbike is. See Monowheel.

Parameters ​
ParameterType
specMonowheelSpec
Returns ​

Monowheel

createMotorcycle() ​
ts
createMotorcycle(spec): Motorcycle;

Make a body that is already in the world a motorbike: two wheels on springs, an engine, and Jolt's own motorcycle controller, which leans it into a turn and holds it upright at rest. See Motorcycle.

Parameters ​
ParameterType
specMotorcycleSpec
Returns ​

Motorcycle

createRagdoll() ​
ts
createRagdoll(spec): Ragdoll;

A character's parts as bodies joined by swing-twist joints, in this world: they fall onto whatever the world holds. See Ragdoll.

While any ragdoll has a part the physics leads and awake, every step runs RAGDOLL_STEPS collision steps with the ragdolls' flesh before each.

Parameters ​
ParameterType
specRagdollSpec
Returns ​

Ragdoll

dispose() ​
ts
dispose(): void;

Free every Jolt object this world owns.

Returns ​

void

drainContacts() ​
ts
drainContacts(out): number;

Move queued contacts into out.

Parameters ​
ParameterType
outContactRecord[]
Returns ​

number

groundState() ​
ts
groundState(id): GroundState;

What a character body is standing on, as of the last step.

Parameters ​
ParameterType
idnumber
Returns ​

GroundState

isAwake() ​
ts
isAwake(id): boolean;

Whether the physics has a body awake: moving, or not yet come to rest. Unknown ids, static bodies and bodies taken out read false; a character is never asleep and reads true.

Parameters ​
ParameterType
idnumber
Returns ​

boolean

moveCharacter() ​
ts
moveCharacter(id, desiredVelocity): void;

Set the desired world-space velocity of a character body for the next step.

Parameters ​
ParameterType
idnumber
desiredVelocityVec3
Returns ​

void

overlapSphere() ​
ts
overlapSphere(
   center, 
   radius, 
   mask
): number[];

Guest body ids overlapping a sphere, nearest first.

Parameters ​
ParameterType
centerVec3
radiusnumber
masknumber
Returns ​

number[]

overlapSphereInto() ​
ts
overlapSphereInto(
   center, 
   radius, 
   mask, 
   out
): number;

Zero-allocation form of PhysicsWorld.overlapSphere.

Parameters ​
ParameterType
centerVec3
radiusnumber
masknumber
outUint32Array
Returns ​

number

ragdollPartOf() ​
ts
ragdollPartOf(id): 
  | {
  part: number;
  ragdoll: Ragdoll;
}
  | null;

Which ragdoll and part a query's body id names, or null for an ordinary body.

Parameters ​
ParameterType
idnumber
Returns ​

| { part: number; ragdoll: Ragdoll; } | null

raycast() ​
ts
raycast(
   origin, 
   direction, 
   maxDistance, 
   mask
): RayHit | null;

Closest hit along a ray, or null. The returned object is reused.

Parameters ​
ParameterType
originVec3
directionVec3
maxDistancenumber
masknumber
Returns ​

RayHit | null

raycastBatch() ​
ts
raycastBatch(
   rays, 
   mask, 
   out
): number;

Many rays, one call.

Parameters ​
ParameterType
raysFloat32Array
masknumber
outFloat32Array
Returns ​

number

readBodies() ​
ts
readBodies(out): number;

Write stride-15 body rows into out. See PhysicsWorld.readBodies.

Parameters ​
ParameterType
outFloat32Array
Returns ​

number

readBodyBounds() ​
ts
readBodyBounds(
   id, 
   out, 
   offset
): boolean;

Local-space bounds and world transform of a body, for debug drawing.

Parameters ​
ParameterType
idnumber
outFloat32Array
offsetnumber
Returns ​

boolean

readBodyPose() ​
ts
readBodyPose(
   id, 
   out, 
   offset
): boolean;

World transform of a body alone, when its bounds are already known.

Parameters ​
ParameterType
idnumber
outFloat32Array
offsetnumber
Returns ​

boolean

removeBody() ​
ts
removeBody(id): void;

Destroy a body and release its shape reference. Unknown ids are ignored.

Parameters ​
ParameterType
idnumber
Returns ​

void

setEnabled() ​
ts
setEnabled(id, enabled): void;

Take a body out of the simulation without destroying it, or put it back.

Parameters ​
ParameterType
idnumber
enabledboolean
Returns ​

void

setTransform() ​
ts
setTransform(
   id, 
   position, 
   rotation, 
   teleport?
): void;

Teleport a body. Velocities are left alone unless teleport says otherwise.

Parameters ​
ParameterTypeDescription
idnumberGuest body handle.
positionVec3New world-space position.
rotationQuatNew world-space orientation, xyzw.
teleport?booleanTrue for a hard cut: the body's linear and angular velocities are zeroed too, and a character forgets the velocity it was asked for. False (the default) moves the body and lets it keep moving.
Returns ​

void

setVelocity() ​
ts
setVelocity(
   id, 
   linear, 
   angular
): void;

Set linear and angular velocity.

Parameters ​
ParameterType
idnumber
linearVec3
angularVec3
Returns ​

void

sleep() ​
ts
sleep(id): void;

Put a body to sleep where it is: it stays exactly there, costing nothing, until something touches it or a command moves it. Unknown ids, static bodies and characters are left alone.

Parameters ​
ParameterType
idnumber
Returns ​

void

step() ​
ts
step(dt, substeps?): number;

Advance the simulation.

Parameters ​
ParameterType
dtnumber
substeps?number
Returns ​

number


PhysicsWorldOptions ​

Options for createPhysicsWorld.

Extended by ​

Properties ​

characterStepUp? ​
ts
optional characterStepUp?: number;

How high a step a walking character body climbs without jumping, in metres. Defaults to 0.4, a tall stair. A world whose collision is rough (a made place, where a chest is a lump the walker would otherwise walk up like a stair) wants less: 0.2 keeps the walker on the floor.

characterStrength? ​
ts
optional characterStrength?: number;

The most force a walking character body puts on a body it walks into, in newtons. Defaults to 100, Jolt's own: enough to slide a 5 kg box, and it stops dead at a 20 kg trunk. A person leaning in manages a few hundred; a game whose walker should shove furniture about sets 400 or so.

gravity? ​
ts
optional gravity?: Vec3;

Gravity in metres per second squared. Defaults to [0, -9.81, 0].

layers? ​
ts
optional layers?: LayerOptions;

Object-layer slot tuning. See LayerOptions.

maxBodies? ​
ts
optional maxBodies?: number;

Hard ceiling on simultaneous bodies. Defaults to 4096.

maxBodyPairs? ​
ts
optional maxBodyPairs?: number;

Maximum body pairs the broad phase tracks. Defaults to maxBodies * 2.

maxContactConstraints? ​
ts
optional maxContactConstraints?: number;

Maximum contact constraints per step. Defaults to maxBodies.

maxContactsPerStep? ​
ts
optional maxContactsPerStep?: number;

Contact records the world keeps for one step. Defaults to 256.

The pool is allocated up front and never grows, because growing it would allocate inside Jolt's own Step(). A step that produces more reportable contacts than this drops the surplus and warns once — raise the ceiling if the game really does want that many in a single step.


Ragdoll ​

A live ragdoll. Poses are 7 floats (px py pz qx qy qz qw), velocities 6 (vx vy vz wx wy wz), all world space; k is a part's index in the spec.

Properties ​

awake ​
ts
readonly awake: boolean;

True while any simulated part is still moving.

count ​
ts
readonly count: number;

How many parts.

inertia ​
ts
readonly inertia: Float64Array;
load ​
ts
readonly load: Float64Array;

What each joint carries at rest: the weight of everything hanging from it times its lever (N m per radian of lean), and the inertia of all of it about the joint (kg m2). A joint's muscles are sized from these.

overshoot ​
ts
readonly overshoot: number;

The farthest any joint is past its range now, radians (0: all inside).

partIds ​
ts
readonly partIds: readonly number[];

The body ids the world's queries report for the parts (raycast, overlapSphere), in part order: a ray that lands on a fallen body says which part.

Methods ​

damping() ​
ts
damping(k, angular): void;

How quickly part k's own spin dies away, per second (soft tissue: a limp body does not flail).

Parameters ​
ParameterTypeDescription
knumberThe part.
angularnumberPer second.
Returns ​

void

dispose() ​
ts
dispose(): void;

Take the ragdoll out of the world.

Returns ​

void

drive() ​
ts
drive(
   k, 
   target, 
   strength, 
   stiff?
): void;

The joint of part k pulls it toward target (its turn against its parent's body: parent^-1 . part, xyzw) with strength (0: no muscle, the joint only has its friction; 1: a braced body). The muscle is a spring sized to what the joint carries: stiff times its load, damped near critically for the inertia hanging from it, its torque capped at the joint's own strength.

Parameters ​
ParameterTypeDescription
knumberThe part.
targetQuat | nullThe turn, or null to let go.
strengthnumber0..1.
stiff?numberThe spring over the load; 6 when omitted.
Returns ​

void

gravity() ​
ts
gravity(k, share): void;

How much of gravity part k feels (1: all of it; a body on its feet holds most of its own weight with its posture muscles).

Parameters ​
ParameterTypeDescription
knumberThe part.
sharenumber0..1.
Returns ​

void

impulse() ​
ts
impulse(
   k, 
   impulse, 
   at
): void;

A push of impulse newton-seconds at at (world) on part k. A led part is left be.

Parameters ​
ParameterTypeDescription
knumberThe part.
impulseVec3Newton-seconds.
atVec3World point.
Returns ​

void

isKinematic() ​
ts
isKinematic(k): boolean;

Whether a part is led by the pose.

Parameters ​
ParameterTypeDescription
knumberThe part.
Returns ​

boolean

True for kinematic.

kinematic() ​
ts
kinematic(k, on): void;

A part led by the pose (kinematic) or by the physics (dynamic).

Parameters ​
ParameterTypeDescription
knumberThe part.
onbooleanTrue for kinematic.
Returns ​

void

moveKinematic() ​
ts
moveKinematic(
   k, 
   pose, 
   offset, 
   dt
): void;

A led part to where the pose has it, arriving in dt seconds (it moves there with the speed that takes, so a hit that lets it go keeps that speed).

Parameters ​
ParameterTypeDescription
knumberThe part.
poseFloat32Array7 floats at offset.
offsetnumberWhere the pose starts in pose.
dtnumberSeconds.
Returns ​

void

place() ​
ts
place(poses, velocities?): void;

Every part to the pose given, moving as given. Parts that overlap there and are not neighbours are kept from colliding with each other until the next place (a hand in a pocket does not blow the hip away).

Parameters ​
ParameterTypeDescription
posesFloat32Array7 floats per part.
velocities?Float32Array<ArrayBufferLike>6 floats per part, of the joint; omit for still.
Returns ​

void

readPose() ​
ts
readPose(
   k, 
   out, 
   offset
): void;

Part k's joint place and turn now, 7 floats at offset.

Parameters ​
ParameterTypeDescription
knumberThe part.
outFloat32ArrayDestination.
offsetnumberWhere to write.
Returns ​

void

readVelocity() ​
ts
readVelocity(
   k, 
   out, 
   offset
): void;

Part k's speed now, of its joint (metres a second) and its turn (radians a second), 6 floats at offset.

Parameters ​
ParameterTypeDescription
knumberThe part.
outFloat32ArrayDestination.
offsetnumberWhere to write.
Returns ​

void

tone() ​
ts
tone(k, frictionNm): void;

The joint's friction, N m (its tone when limp).

Parameters ​
ParameterTypeDescription
knumberThe part.
frictionNmnumberNewton metres.
Returns ​

void


RagdollLimit ​

The range of one joint, in the world frame at the ragdoll's rest pose.

twist is the child's bone at rest (or a hinge's axis), plane square to it; centre turns the parent's axes to the middle of the joint's range (identity: the rest pose is the middle). planeHalf limits the turn about the plane axis, which swings the bone toward the normal axis (twist x plane); normalHalf the turn about the normal axis. A hinge has both at 0 and its fold in the twist range. Angles in radians.

Properties ​

centre ​
ts
centre: Quat;

The middle of the joint's range, as a turn of the parent's axes, xyzw.

damp ​
ts
damp: number;

Per second: how fast a turn in the joint dies away (its viscosity).

friction ​
ts
friction: number;

N m of friction in the joint: a body gone limp still has some tone.

margin ​
ts
margin: number;

Radians past the range where a spring takes over before the hard stop.

normalHalf ​
ts
normalHalf: number;

Radians: the turn about the normal axis (twist x plane).

plane ​
ts
plane: Vec3;

Square to twist, world, unit.

planeHalf ​
ts
planeHalf: number;

Radians: the turn about the plane axis.

torque ​
ts
torque: number;

How strong the joint's muscles are, N m at full effort.

twist ​
ts
twist: Vec3;

The twist axis at rest, world, unit.

twistMax ​
ts
twistMax: number;
twistMin ​
ts
twistMin: number;

Radians: the twist's range, twistMin at most 0, twistMax at least 0.


RagdollPart ​

One part of a ragdoll.

Properties ​

friction? ​
ts
optional friction?: number;

Its own friction, 0..1, over the material's.

limit ​
ts
limit: RagdollLimit | null;

Its joint's range, or null for the root.

linearCast? ​
ts
optional linearCast?: boolean;

Use continuous collision (a part a hand's width across may not pass through the floor in one step).

mass ​
ts
mass: number;

Kilograms.

name ​
ts
name: string;

A name, for messages.

noCollide? ​
ts
optional noCollide?: number[];

Parts this one never collides with, besides its parent and its siblings.

parent ​
ts
parent: number;

The part it hangs from, -1 for the root (the hips). Parents come before children.

restPosition ​
ts
restPosition: Vec3;

Where its joint is at rest (the body's origin), world.

restRotation ​
ts
restRotation: Quat;

Its joint's turn at rest (the body's frame), world, xyzw.

shape ​
ts
shape: RagdollShape;

Its collision shape at rest.


RagdollSpec ​

Everything needed to build one ragdoll.

Properties ​

layer ​
ts
layer: number;

What the parts are, as a layer bitset.

mask ​
ts
mask: number;

What the parts collide with, as a bitset of other bodies' layers.

parts ​
ts
parts: RagdollPart[];

The parts, the root first, every parent before its children.


RayHit ​

One raycast result. The instance returned by raycast is reused.

Properties ​

body ​
ts
body: number;

Guest body id that was hit.

distance ​
ts
distance: number;

Distance from the ray origin, metres.

nx ​
ts
nx: number;

Surface normal at the hit, x.

ny ​
ts
ny: number;

Surface normal, y.

nz ​
ts
nz: number;

Surface normal, z.

px ​
ts
px: number;

Hit point, x.

py ​
ts
py: number;

Hit point, y.

pz ​
ts
pz: number;

Hit point, z.

Type Aliases ​

BodyKind ​

ts
type BodyKind = "static" | "dynamic" | "kinematic" | "character";

Body class. Mirrors WIT body-kind, except that WIT spells static as fixed because static is a WIT keyword.


ContactPhase ​

ts
type ContactPhase = "begin" | "stay" | "end";

Which side of a contact this record describes. Mirrors WIT contact-phase.


GroundState ​

ts
type GroundState = "on-ground" | "on-steep-ground" | "not-supported" | "in-air";

What a character controller is standing on.


JoltInstance ​

ts
type JoltInstance<K> = JoltModule[K] extends (...args) => infer R ? R : never;

Instance type of a Jolt class, e.g. JoltInstance<'Vec3'>.

Type Parameters ​

Type Parameter
K extends keyof JoltModule

JoltModule ​

ts
type JoltModule = Awaited<ReturnType<typeof initJolt>>;

The initialised Jolt wasm module: every Jolt class, enum constant and helper (destroy, wrapPointer, ...) hangs off this object.

It mirrors the Jolt C++ API one to one, so the C++ reference is the documentation.


JoltShape ​

ts
type JoltShape = JoltInstance<"Shape">;

A reference-counted Jolt collision shape.


Quat ​

ts
type Quat = readonly [number, number, number, number];

A unit quaternion in xyzw order, matching three.js and Jolt.


RagdollShape ​

ts
type RagdollShape = 
  | {
  a: Vec3;
  b: Vec3;
  kind: "capsule";
  radius: number;
}
  | {
  centre: Vec3;
  half: Vec3;
  kind: "box";
  rotation: Quat;
  round: number;
};

A part's collision shape, in the world frame at the ragdoll's rest pose.


ShapeKind ​

ts
type ShapeKind = "box" | "sphere" | "capsule" | "cylinder" | "mesh" | "convex";

Collision shape family. Mirrors WIT shape-kind.


Vec3 ​

ts
type Vec3 = readonly [number, number, number];

A position or direction, in metres.

Variables ​

BODY_STRIDE ​

ts
const BODY_STRIDE: 15 = 15;

Floats per row in the buffer PhysicsWorld.readBodies fills.


MONOWHEEL ​

ts
const MONOWHEEL: Readonly<{
  askedEase: 0.12;
  askedIdle: 6;
  askedLevel: 1500;
  askedLevelMost: 60;
  askedLevelRate: 24;
  askedOver: 0.2;
  askedSteer: 0.1;
  askedSteps: 3;
  crawl: 0.6;
  crawlLean: 0.105;
  gripPeak: 2.6;
  gripSlide: 2.2;
  headingLost: 0.5;
  headingRate: 4;
  holdEase: 0.15;
  holdLag: 5;
  holdNear: 0.02;
  holdRate: 3;
  lean: number;
  leanDamping: 0.9;
  leanFollow: 14;
  leanRate: 30;
  leanSpurt: 16;
  leanSwing: 2.2;
  levelDamping: 0.8;
  levelRate: 12;
  ringInertia: 10;
  steerRate: 6;
  steerTurn: 2;
  turnLearn: 0.2;
  turnSeconds: 0.03;
}>;

The balance's numbers.


MOTORCYCLE_WHEEL_STRIDE ​

ts
const MOTORCYCLE_WHEEL_STRIDE: 4 = 4;

How many numbers Motorcycle.read writes per wheel.


PACKAGE ​

ts
const PACKAGE: "@gameable/physics-jolt";

Package identity marker for gameable/physics.

Example ​

ts
import { PACKAGE } from 'gameable/physics';

console.log(PACKAGE); // 'gameable/physics'

RAGDOLL_ID_BASE ​

ts
const RAGDOLL_ID_BASE: number;

The first body id the world mints for a ragdoll's parts. A guest mints its own ids from 1 upward; a query that lands on a part reports an id at or past this, and PhysicsWorld.ragdollPartOf says which part of which ragdoll it is.


RAGDOLL_MATERIAL ​

ts
const RAGDOLL_MATERIAL: Readonly<{
  angularDamping: 0.05;
  friction: 0.6;
  linearDamping: 0.02;
  restitution: 0.1;
}>;

The materials of a ragdoll's parts, and the damping they carry of their own (the joints' viscosity does the rest).


RAGDOLL_SOFT ​

ts
const RAGDOLL_SOFT: 1.5 = 1.5;

The soft end of a range: its spring per radian of the margin, in units of the weight the joint carries.


RAGDOLL_STEPS ​

ts
const RAGDOLL_STEPS: 3 = 3;

Collision steps per fixed step while a ragdoll is awake: 180 a second at 60.


RAY_HIT_STRIDE ​

ts
const RAY_HIT_STRIDE: 9 = 9;

Floats per row of the output buffer PhysicsWorld.raycastBatch fills.


RAY_STRIDE ​

ts
const RAY_STRIDE: 7 = 7;

Floats per row of the input buffer PhysicsWorld.raycastBatch reads.

Functions ​

clampToRange() ​

ts
function clampToRange(
   q, 
   limit, 
   out
): boolean;

The nearest turn to q (a joint's turn in its own frame: x the twist axis, y the plane axis, z the normal) inside the joint's range, into out; true when q was past it. The twist is clamped to its range, the swing to the ellipse of its two half angles, as the physics' own joint measures them.

Parameters ​

ParameterTypeDescription
qQuaternionLikeThe turn (three's Quaternion, or anything with its x y z w).
limitRagdollLimitThe joint's range.
outQuaternionSettableThe nearest turn inside the range (written with set(x, y, z, w)).

Returns ​

boolean

True when q was past the range.


compoundShapeFromHulls() ​

ts
function compoundShapeFromHulls(
   jolt, 
   hulls, 
   options?
): Shape;

Several convex shapes as one shape: a table's four legs and its top, not the block round them.

Each set of points is wrapped in its own convex hull and the hulls are held together as one static compound, in the frame the points are given in. Like a single hull it can back a dynamic body, and what is open between the hulls stays open: a thing can pass under the top and between the legs. A set too small or too flat to make a hull is left out.

The returned shape carries one reference owned by you; see meshShapeFromGeometry.

Parameters ​

ParameterTypeDescription
jolttypeof JoltThe initialised Jolt module.
hullsreadonly Float32Array<ArrayBufferLike>[]One array of point positions for each hull, stride 3 (x, y, z), in metres.
optionsOmit<ConvexHullOptions, "centreOfMassOffset">Hull build tuning, used for every hull (the centre-of-mass offset is not).

Returns ​

Shape

A shape with a reference count of one: the one hull itself when only one could be built.

Throws ​

When no hull could be built.

Example ​

ts
import { compoundShapeFromHulls, loadJolt } from 'gameable/physics';

const jolt = await loadJolt();
const box = (x: number): Float32Array =>
  new Float32Array([0, 1].flatMap((a) => [0, 1].flatMap((b) => [0, 1].flatMap((c) => [x + a, b, c]))));
const twoLegs = compoundShapeFromHulls(jolt, [box(-2), box(2)]);
twoLegs.Release();

convexHullFromPoints() ​

ts
function convexHullFromPoints(
   jolt, 
   points, 
   options?
): Shape;

Wrap a point cloud in its convex hull.

Unlike a mesh shape a convex hull can back a dynamic body, so this is the right shape for props lifted out of a splat scene: feed it the point cloud of the region you want solid and Jolt builds the tightest convex volume around it.

The returned shape carries one reference owned by you; see meshShapeFromGeometry.

Parameters ​

ParameterTypeDescription
jolttypeof JoltThe initialised Jolt module.
pointsFloat32ArrayPoint positions, stride 3 (x, y, z), in metres.
optionsConvexHullOptionsHull build tuning.

Returns ​

Shape

A shape with a reference count of one.

Throws ​

When there are fewer than four points or Jolt cannot build a hull.

Example ​

ts
import { convexHullFromPoints, loadJolt } from 'gameable/physics';

const jolt = await loadJolt();
const cube = new Float32Array([
  -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1,
  -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1,
]);
const hull = convexHullFromPoints(jolt, cube);
hull.Release();

createContactRecord() ​

ts
function createContactRecord(): ContactRecord;

Allocate one pooled ContactRecord.

Returns ​

ContactRecord

A zeroed record.

Example ​

ts
import { createContactRecord, type ContactRecord } from 'gameable/physics';

const pool: ContactRecord[] = [createContactRecord(), createContactRecord()];

createPhysicsWorld() ​

ts
function createPhysicsWorld(jolt, options?): PhysicsWorld;

Create a Jolt simulation.

Parameters ​

ParameterTypeDescription
jolttypeof JoltThe module from loadJolt.
optionsPhysicsWorldOptionsGravity, capacity and layer tuning.

Returns ​

PhysicsWorld

A live world. Call PhysicsWorld.dispose when done.

Example ​

ts
import { createPhysicsWorld, loadJolt } from 'gameable/physics';

const world = createPhysicsWorld(await loadJolt(), { gravity: [0, -9.81, 0] });
world.addBody({
  id: 1,
  shape: 'box',
  dims: [10, 0.5, 10],
  position: [0, -0.5, 0],
  rotation: [0, 0, 0, 1],
  mass: 0,
  kind: 'static',
  layer: 0b10,
  mask: 0xffff,
  friction: 0.6,
  restitution: 0,
});
world.step(1 / 60);
world.dispose();

isJoltLoaded() ​

ts
function isJoltLoaded(): boolean;

Whether loadJolt has been called in this process.

Returns ​

boolean

True once the singleton exists, in flight or resolved.

Example ​

ts
import { isJoltLoaded, loadJolt } from 'gameable/physics';

if (!isJoltLoaded()) await loadJolt();

loadJolt() ​

ts
function loadJolt(options?): Promise<typeof Jolt>;

Instantiate the Jolt wasm module, once per page.

The module is a process-wide singleton: every call returns the same promise, so registering two physics worlds costs one wasm instantiation. Passing a different wasmUrl after the singleton exists is a bug and throws rather than silently loading a second copy of the engine. A call that names no wasmUrl after the singleton exists is how a package that only needs the module (to build a shape) gets it: it returns the one already loaded.

Parameters ​

ParameterTypeDescription
optionsLoadJoltOptionsWhere to fetch the wasm binary from.

Returns ​

Promise<typeof Jolt>

The initialised Jolt module.

Throws ​

When called again with a different wasmUrl.

Example ​

ts
import { loadJolt } from 'gameable/physics';

const jolt = await loadJolt();
const up = new jolt.Vec3(0, 1, 0);
jolt.destroy(up); // Jolt never frees anything for you.

meshShapeFromGeometry() ​

ts
function meshShapeFromGeometry(
   jolt, 
   positions, 
   indices, 
   options?
): Shape;

Turn indexed triangle geometry into a Jolt MeshShape.

A MeshShape is a triangle soup with a BVH over it: it can only back a static body, which is exactly what splat-environment colliders and baked level geometry are. Building one is expensive (it constructs a tree), so build it once at load time and share it across every body that needs it.

The returned shape carries one reference owned by you. addBody takes its own reference, so the shape survives bodies being removed; call shape.Release() when the geometry itself is gone.

Parameters ​

ParameterTypeDescription
jolttypeof JoltThe initialised Jolt module.
positionsFloat32ArrayVertex positions, stride 3 (x, y, z), in metres.
indicesUint32ArrayTriangle indices, three per triangle, into positions.
optionsMeshShapeOptionsBuild tuning.

Returns ​

Shape

A shape with a reference count of one.

Throws ​

When the arrays are malformed or Jolt rejects the mesh.

Example ​

ts
import { loadJolt, meshShapeFromGeometry } from 'gameable/physics';

const jolt = await loadJolt();
const positions = new Float32Array([0, 0, 0, 1, 0, 0, 0, 0, 1]);
const indices = new Uint32Array([0, 1, 2]);
const shape = meshShapeFromGeometry(jolt, positions, indices);
shape.Release();

physics() ​

ts
function physics(options?): EngineModule;

The Jolt physics EngineModule.

Registered in the engine's module list, it loads the Jolt wasm module in init, publishes the world as the physics service, and steps the simulation once per fixed step — never in update, because reading body state there gives you an interpolated pose, not a simulated one.

Parameters ​

ParameterTypeDescription
optionsPhysicsOptionsGravity, capacity, layer tuning and the wasm location.

Returns ​

EngineModule

A module to hand to createEngine({ modules: [...] }).

Example ​

ts
import { createEngine } from 'gameable/core';
import { physics } from 'gameable/physics';

const engine = await createEngine({
  canvas,
  manifest,
  modules: [physics({ gravity: [0, -9.81, 0] })],
});
const hit = engine.get('physics').raycast([0, 2, 0], [0, -1, 0], 10, 0xffff);

segmentDistance() ​

ts
function segmentDistance(
   p1, 
   q1, 
   p2, 
   q2
): number;

The shortest distance between two segments (their ends three's Vector3, or anything with its x y z).

Parameters ​

ParameterTypeDescription
p1Vector3LikeStart of the first.
q1Vector3LikeEnd of the first.
p2Vector3LikeStart of the second.
q2Vector3LikeEnd of the second.

Returns ​

number

Metres.