# Core utilities

> Reference for @apricot/core: the framework-free engine under @apricot/react. Utilities apps use (seededRandom, disposeObject, mergeColoredParts, setShadow, visibleBox, fitCamera), the classes behind the components, and the @apricot/core/models entry point.

`@apricot/core` is the engine without React: the renderer, frame loop, materials, camera rig, physics and timelines. `@apricot/react` re-exports what apps need (`Path`, `Trip`, `CAMERA_VIEWS`, `DAY`, `definePreset`, `defineEnvironment`, `createMaterial`, `PresetMaterial` and the types), so most apps import from it alone. Import from `@apricot/core` for the utilities below.

```ts
import { disposeObject, mergeColoredParts, seededRandom, setShadow } from "@apricot/core";
```

> [!NOTE]
> Importing `@apricot/core` installs small polyfills (such as `TextDecoder`) before three.js loads. `@apricot/react` imports it for you.

## Utilities

| Export | Signature | Description |
| --- | --- | --- |
| `seededRandom` | `(seed: number) => () => number` | Deterministic pseudo-random numbers in [0, 1). Same seed, same sequence: layouts that look the same every launch |
| `disposeObject` | `(root: Object3D) => void` | Frees the geometries, materials and textures of `root` and everything under it. Call it on unmount for objects you built |
| `mergeColoredParts` | `(parts: ColoredPart[]) => BufferGeometry` | Bakes several geometries, each with a colour, into one geometry with vertex colours: one draw call. UVs are dropped |
| `setShadow` | `(object, { cast?, receive? } \| undefined) => void` | Overrides whether a three.js object casts and receives shadows. On a directional light, `cast: true` makes it the one that casts |
| `visibleBox` | `(camera, depth = 0, z = 0) => Bounds` | The box of world space the camera sees, `depth` deep on each side of the plane at `z`. For filling the screen |
| `fitDistance` | `(camera, width, height, margin = 0.1) => number` | How far the camera must be for an area to fill the view |
| `fitCamera` | `(camera, width, height, { margin, target })` | Moves the camera along its line of sight so an area fits (what `<FitCamera>` calls) |
| `stepSpin` | `(object, speed, axis, delta) => boolean` | One frame of `<Spin>` |

`ColoredPart`: `{ geometry, color, matrix? }`, where `color` is a colour, a function of each vertex's position, or `"vertex"` to keep the geometry's own colours.

`Bounds`: `{ min: Vec3, max: Vec3 }`.

## Constants

| Export | Description |
| --- | --- |
| `CAMERA_VIEWS` | The built-in camera views (see [Cameras](https://matthiasbrandolin.dev/apricot/reference/cameras#camera_views)) |
| `DAY` | The default `DaylightKey[]` for `<Daylight>` |
| `LOOKS` | The `soft`, `studio` and `flat` look specs |
| `STUDIO` | The default studio environment |

## Engine classes

The components are thin wrappers around these. Use them for code outside React or for your own components.

| Class | Behind | Description |
| --- | --- | --- |
| `ApricotScene` | `<Scene>` | Renderer, camera, frame loop, taps, shadows, diagnostics |
| `PresetMaterial` | `material` props | A preset material with live colour, roughness and metalness |
| `CameraRig` (the core class) | `<CameraRig>` | Views, arcs, orbit, framing |
| `FollowRig` | `<FollowCamera>` | Chase camera |
| `ArcadeVehicle` | `<Vehicle>` | Toy-car physics: `step(delta, { throttle, steer })`, `state` |
| `SphereWorld` | `<Pile>` | Sphere physics solver |
| `Pile` | `<Pile>` | Dropping and piling copies |
| `Path` | `usePath` | Smooth curve with distance queries |
| `Trip` | `useTrip` | Stop-to-stop timeline: `at(seconds)` returns a `TripState` |
| `InstanceSet` | `<Instances>` | Copies of a shape in instanced meshes |
| `BlurLayer` | `<Blur>` | The out-of-focus layer |
| `ClipPlayer` | `animations` | glTF clip playback |
| `SharedCache<T>` | caches | Loads each key once, counts users with `acquire` / `release`, disposes on the last release |

## `@apricot/core/models`

```ts
import { instance, ModelCache, parseModel } from "@apricot/core/models";
```

The glTF loading layer, in a separate entry point so apps without models do not carry three's loader.

| Export | Description |
| --- | --- |
| `parseModel(bytes)` | Parses `.glb` bytes into a `LoadedModel` (`{ scene, animations }`). No Draco, meshopt or KTX2: Hermes has no WebAssembly. Prepare files with `apricot-models` |
| `instance(model)` | A copy of a loaded model to add to a scene. Copies share geometry, materials and textures; rigged models get their own skeleton |
| `ModelCache` | Loads each model once and shares it; the last release disposes it |

Apps normally use `<Model>` and `useModel` from `@apricot/react/model` instead.

## Related

- [Custom geometry and behaviors](https://matthiasbrandolin.dev/apricot/guides/custom).
- [Hooks](https://matthiasbrandolin.dev/apricot/reference/hooks).
