# Physics overview

# Physics overview

Out of the box a Ferret game has the *collision system* of Babylon: a capsule against meshes with `checkCollisions`, layers, triggers and raycasts (`PhysicsService`). **Realistic physics is a separate set of capabilities.** A game, a level, a zone or one entity uses them or does not; nothing realistic runs unless asked, and a game that needs a cannonball does not carry cloth.

Units are SI: metres, kilograms, seconds, newtons, pascals. The world's fixed step drives everything, so a run repeats with the same inputs.

## The host and the kernel

`PhysicsHost` is the home of the capabilities: it owns the **kernel**, the material library, the registry and the fixed order of the step. A kernel is a rigid-body engine behind `PhysicsKernel`:

| Kernel | What it is |
|---|---|
| `LightKernel` | small, deterministic, no dependencies: spheres, boxes and capsules against planes and each other; joints; enough for most games |
| `HavokKernel` | Havok through its own API (no Babylon scene needed, so it runs headless): full shapes, ball / hinge / fixed joints, `noCollide`; the WASM comes from `physics-havok` |

```ts
import { PhysicsHost } from '@ferret/physics';
import { gravity } from '@ferret/physics-gravity';
import { friction } from '@ferret/physics-friction';
import { impact } from '@ferret/physics-impact';

const host = world.addService(new PhysicsHost({ capabilities: [gravity(), friction(), impact()] }));
host.enable('gravity');
host.enable('friction', { scale: 1.2 });

const e = world.spawn('ball', { position: new BABYLON.Vector3(0, 3, 0) });
e.add('RigidBody', { shape: 'sphere', radius: 0.25, mass: 1 });
```

A `RigidBody` component puts a node under the kernel: the node follows the body after every step. Registering a capability makes it *available*; `enable(name, values)` turns it on, `disable(name)` off. A capability that needs bodies refuses to switch on when the kernel has none, and `requires` names the capabilities that must be on first.

## Capabilities

A `Capability` has a name, a **phase**, an optional order inside the phase, defaults, a declared cost, and hooks (`enable`, `disable`, `step`). Capabilities are *independent* (each works alone) and *composable* (they meet in the shared material data and in the order of the step, never in each other's code). A game may write its own against the same interface.

### Phases

The step has a fixed order (`Phase`):

1. **field**: capabilities add forces (gravity, drag, buoyancy, explosions, springs...).
2. The kernel integrates and resolves contacts.
3. **strength**: capabilities act on what the contacts did (damage, breakage).
4. **stretch**: capabilities fix up constraints and soft bodies.

Inside a phase, capabilities run by `order`, ties by name, never by registration order, so the result does not depend on how a game assembled them.

## Scoped values

Every value of a capability has a default and can be overridden at four scopes, narrowest wins: **entity**, **zone**, **level**, **world**, then the default (`ScopedConfig`).

```ts
host.config('gravity').set('world', 'scale', 1);
host.config('gravity').set('zone', 'scale', 0.16, 'moon-pit');   // low gravity inside one zone
host.config('friction').set('entity', 'scale', 0.05, 'ice-block');
```

A level manifest does the same declaratively in its `physics` block (`PhysicsConfig`):

```json
"physics": {
  "capabilities": ["gravity", "media", "friction", "impact"],
  "materials": { "ice": { "friction": 0.03, "restitution": 0.1 } },
  "gravity": { "vector": [0, -9.81, 0] },
  "constraints": [{ "type": "rope", "a": "Beam", "b": "Weight", "length": 3 }]
}
```

Values from the manifest apply while the level is loaded and are cleared when it goes.

## Materials

A `PhysicsMaterial` is data: density, friction, restitution, strengths, heat capacity, and so on. A value that is **not given** means "this capability does not apply to it", not a default: a material without a strength is unbreakable. Two materials meet under a combine rule (`CombineRule`: mean, geometric, min, max, multiply), or under an explicit pair rule. `validateMaterials` checks a table for numbers in sane ranges.

## Budgets and tiers

What a machine can afford is data too: `TIERS` gives each `Tier` (`desktop`, `console`, `mobile`, `low`) a share of the frame for the whole physics step (`stepMs`), a cap on live pieces, and particle budgets for liquids and cloth. The numbers for `desktop` come from `tools/bench`; the other tiers are scaled from them.

The `Governor` watches the measured step time. When it stays over budget it gives up detail in the order of its rules (fewer pieces, then no particle liquids, ...), and takes it back when there is room. Everything the host does is visible in `physics.info` (Commands (skill `ferret`)).

## Where to read next

- [Capability catalogue](capabilities.md): every capability with its package and what it does.
- Linking capabilities (skill `ferret-physics-links`): how a fire heats a pot and steam turns a turbine.
- The API of `@ferret/physics`.
