# Coordinates and units

> Which way is up, where the camera starts, which values are radians and which are degrees, and the units of every number Apricot takes.

Most mistakes in 3D code are unit mistakes. This page lists every convention in one place.

## Axes

Apricot uses three.js's right-handed coordinate system:

| Axis | Positive direction (default camera) |
| --- | --- |
| `x` | right |
| `y` | **up** |
| `z` | towards the viewer (out of the screen) |

The ground is the `x`–`z` plane at `y = 0`.

### The default camera

| Setting | Default |
| --- | --- |
| `position` | `[0, 0, 6]`: 6 units in front of the origin |
| `target` | `[0, 0, 0]`: it looks at the origin, down the −z axis |
| `fov` | `50` degrees (vertical field of view) |
| `near`, `far` | `0.1` and `200`: raise `far` for big scenes |

Change it with `<Scene camera={{ position, target, fov, near, far }}>` (read once at mount), or move it at runtime with [`<CameraRig>`](https://matthiasbrandolin.dev/apricot/guides/camera).

### Which way objects face

- **Models face +z**: their front looks at the default camera. In joints and hinges, `front` is +z, `top` is +y and `left` is +x (the model's own left, as it faces you).
- `<Plane>` faces +z (a wall facing you). For a floor, rotate it: `rotation={[-Math.PI / 2, 0, 0]}`.
- `<Cylinder>`, `<Cone>` and `<Capsule>` stand along y. `<Torus>` lies in the x–y plane (a ring facing you).
- `<Car>` (from `@apricot/assets`) and `<Vehicle>` face +z; a heading of `0` drives towards +z.

## Units

| Quantity | Unit | Examples |
| --- | --- | --- |
| Distance, size | scene units, meant as **metres** | `position`, `size`, `radius`, `Path` distances, `Vehicle` speeds (units/s), shadow `radius` |
| Object rotation | **radians**, Euler `[x, y, z]` (XYZ order) | `rotation` on every object, `Instances` items, `Vehicle` `heading` |
| Rotation speed | **radians per second** | `<Spin speed>` |
| Camera angles | **degrees** | `azimuth`, `elevation`, `fov`, orbit `turn` and `elevation` limits, `drift` (degrees per second) |
| Joint angles | **degrees** | joint `range` |
| Light cone | **radians** | `<SpotLight angle>` |
| Time | **seconds** | `transition`, `duration`, `dwell`, `linger`, `delta` in `useFrame` |
| Screen space | **points** (React Native units) | `inset`, `<Blur radius>`, `Label` layout |
| Time of day | **hours**, 0–24 | `<Daylight time={13.5}>` |
| Progress | `0` to `1` | joint values (0 closed, 1 open), animation clip progress, morph weights |

> [!WARNING]
> Object rotations are **radians**; camera views and joint ranges are **degrees**. `rotation={[0, 90, 0]}` turns an object 90 *radians* (about 14 full turns plus 116°). Write `rotation={[0, Math.PI / 2, 0]}`.

### Why metres matter

Lights, fog, shadows and physics are tuned for real-world sizes. A product is about 0.1–3 units, a car about 4, a building 10–100, a map 1000+. If a scene looks wrong, check the scale first:

- **Objects look tiny or huge:** the camera distance does not match the object size. Use `<FitCamera>` or `<CameraRig>`, which frame the subject automatically.
- **Things vanish in the distance:** raise `camera.far` (default 200).
- **Shadows look blocky in a big scene:** give `shadows={{ radius }}` in metres around what the camera looks at.

## Camera views

`<CameraRig>` places the camera on an orbit around its subject:

| Field | Meaning |
| --- | --- |
| `azimuth` | Degrees around the vertical axis. `0` looks at the front (camera on +z), `90` at the left side (camera on +x), `180` at the back, `-90` at the right side. |
| `elevation` | Degrees above the horizon. `0` is level, `90` looks straight down. |
| `distance` | Units from the target. Leave it out to fit the subject on screen. |
| `target` | The point looked at. Default: the subject's centre. |
| `position` | An exact camera position, instead of the angles. |
| `fov` | Vertical field of view in degrees. |

Built-in views: `front` (0°, 8°), `back` (180°, 8°), `left` (90°, 8°), `right` (−90°, 8°), `top` (0°, 90°) and `three-quarter` (35°, 16°), given as azimuth then elevation.

## Colours

Anything three.js accepts as a colour: a CSS string (`"#ff9f59"`, `"rgb(255, 159, 89)"`, `"tomato"`) or a number (`0xff9f59`). Colours are in sRGB, as you would pick them in a design tool.

## Related

- [Objects and refs](https://matthiasbrandolin.dev/apricot/concepts/objects): positions are relative to the parent.
- [Camera guide](https://matthiasbrandolin.dev/apricot/guides/camera).
