Skip to content

@aosengine/core

Classes

ModuleError

A module that could not be registered, initialised or found.

Extends

  • Error

Constructors

Constructor
ts
new ModuleError(
   moduleId, 
   message, 
   options?
): ModuleError;

Build a module error.

Parameters
ParameterTypeDescription
moduleIdstringModule or service id involved.
messagestringWhat went wrong.
options?ErrorOptionsStandard Error options, used to keep the cause.
Returns

ModuleError

Overrides
ts
Error.constructor

Properties

moduleId
ts
readonly moduleId: string;

The module or service id involved.


SceneGraph

Maps entity ids to scene objects.

Constructors

Constructor
ts
new SceneGraph(scene, name?): SceneGraph;

Build a scene graph and attach its root to the scene.

Parameters
ParameterTypeDefault valueDescription
sceneSceneundefinedScene to attach to.
namestring'aosengine:root'Name given to the root group, for debugging.
Returns

SceneGraph

Properties

root
ts
readonly root: Group;

Group every spawned object is parented under.

scene
ts
readonly scene: Scene;

The scene the root was added to.

Accessors

size
Get Signature
ts
get size(): number;

How many entities are in the graph.

Returns

number

The entity count.

Methods

despawn()
ts
despawn(id): boolean;

Remove an entity.

Children are re-parented to the root rather than removed with it, so a despawn cannot silently take a subtree the caller still tracks. Despawn them explicitly if that is what you want.

Parameters
ParameterTypeDescription
idnumberEntity id.
Returns

boolean

True when the entity existed.

dispose()
ts
dispose(): void;

Remove every entity and detach the root from the scene.

Returns

void

get()
ts
get(id): Object3D<Object3DEventMap> | undefined;

Look up an entity's object.

Parameters
ParameterTypeDescription
idnumberEntity id.
Returns

Object3D<Object3DEventMap> | undefined

The object, or undefined when the id is not spawned.

idOf()
ts
idOf(object): number;

The entity id an object was spawned under.

Parameters
ParameterTypeDescription
objectObject3DAny object in the graph.
Returns

number

The id, or 0 when the object was not spawned here.

ids()
ts
ids(): IterableIterator<number>;

Every spawned entity id, in insertion order.

Returns

IterableIterator<number>

An iterator over ids.

setParent()
ts
setParent(id, parentId?): void;

Re-parent an entity.

Parameters
ParameterTypeDefault valueDescription
idnumberundefinedEntity id to move.
parentIdnumberNO_ENTITYNew parent's entity id, or 0 for the root.
Returns

void

spawn()
ts
spawn(
   id, 
   object, 
   parentId?
): Object3D;

Add an object under an entity id.

Parameters
ParameterTypeDefault valueDescription
idnumberundefinedEntity id. Must be a positive integer; 0 is the root.
objectObject3DundefinedThe object to add.
parentIdnumberNO_ENTITYParent entity id, or 0 for the root.
Returns

Object3D

The object, so calls can be chained.

Example
ts
import { SceneGraph } from '@aosengine/core';
import { Group, Scene } from 'three/webgpu';

const graph = new SceneGraph(new Scene());
graph.spawn(1, new Group());
graph.spawn(2, new Group(), 1); // child of entity 1

TransformStore

Previous and current position, rotation and scale for a set of entity ids.

Constructors

Constructor
ts
new TransformStore(capacity?): TransformStore;

Build a transform store.

Parameters
ParameterTypeDefault valueDescription
capacitynumberDEFAULT_TRANSFORM_CAPACITYSlots to reserve up front.
Returns

TransformStore

Accessors

capacity
Get Signature
ts
get capacity(): number;

Slots currently allocated.

Returns

number

The number of addressable entity slots.

Methods

clear()
ts
clear(id): void;

Forget an entity. Its slot is reset to the identity transform.

Parameters
ParameterTypeDescription
idnumberEntity id.
Returns

void

commit()
ts
commit(): void;

Make the current transform the previous one, for every slot.

Call once per fixed step, before that step writes new values.

Returns

void

ensure()
ts
ensure(id): void;

Grow so that id is addressable.

Capacity doubles until it fits, so a run of spawn calls is amortised O(1).

Parameters
ParameterTypeDescription
idnumberEntity id that must fit.
Returns

void

getPosition()
ts
getPosition(id, out): number[] | Float32Array<ArrayBufferLike>;

Read the current position into out.

Parameters
ParameterTypeDescription
idnumberEntity id.
outnumber[] | Float32Array<ArrayBufferLike>A length-3 array to fill.
Returns

number[] | Float32Array<ArrayBufferLike>

out.

getQuaternion()
ts
getQuaternion(id, out): number[] | Float32Array<ArrayBufferLike>;

Read the current rotation into out.

Parameters
ParameterTypeDescription
idnumberEntity id.
outnumber[] | Float32Array<ArrayBufferLike>A length-4 array to fill.
Returns

number[] | Float32Array<ArrayBufferLike>

out.

has()
ts
has(id): boolean;

Whether an entity has ever been written.

Parameters
ParameterTypeDescription
idnumberEntity id.
Returns

boolean

True when the slot holds a transform.

set()
ts
set(
   id, 
   px, 
   py, 
   pz, 
   qx, 
   qy, 
   qz, 
   qw, 
   sx, 
   sy, 
   sz
): void;

Write a whole transform at once. This is the packed-buffer entry point.

Parameters
ParameterTypeDescription
idnumberEntity id.
pxnumberPosition x.
pynumberPosition y.
pznumberPosition z.
qxnumberQuaternion x.
qynumberQuaternion y.
qznumberQuaternion z.
qwnumberQuaternion w.
sxnumberScale x.
synumberScale y.
sznumberScale z.
Returns

void

setPosition()
ts
setPosition(
   id, 
   x, 
   y, 
   z
): void;

Write the current position of an entity.

The first write to a slot also seeds the previous transform, so a freshly spawned entity does not interpolate in from the origin.

Parameters
ParameterTypeDescription
idnumberEntity id.
xnumberPosition x.
ynumberPosition y.
znumberPosition z.
Returns

void

setQuaternion()
ts
setQuaternion(
   id, 
   x, 
   y, 
   z, 
   w
): void;

Write the current rotation of an entity.

Parameters
ParameterTypeDescription
idnumberEntity id.
xnumberQuaternion x.
ynumberQuaternion y.
znumberQuaternion z.
wnumberQuaternion w.
Returns

void

setScale()
ts
setScale(
   id, 
   x, 
   y, 
   z
): void;

Write the current scale of an entity.

Parameters
ParameterTypeDescription
idnumberEntity id.
xnumberScale x.
ynumberScale y.
znumberScale z.
Returns

void

snap()
ts
snap(id): void;

Collapse one entity's history, so the next frame does not interpolate.

Use after a teleport.

Parameters
ParameterTypeDescription
idnumberEntity id.
Returns

void

writeInterpolated()
ts
writeInterpolated(
   id, 
   object, 
   alpha
): boolean;

Write the blend of previous and current onto an Object3D.

Parameters
ParameterTypeDescription
idnumberEntity id.
objectObject3DTarget object; its position, quaternion and scale are written.
alphanumberInterpolation factor, normally the loop's alpha in [0, 1).
Returns

boolean

True when the entity existed and the object was written.

Interfaces

CreateEngineOptions

Options accepted by createEngine.

Properties

canvas
ts
readonly canvas: HTMLCanvasElement;

The canvas to render into. The engine observes it for size changes.

debug?
ts
readonly optional debug?: boolean;

Create the F3 debug overlay. Defaults to false.

dracoDecoderPath?
ts
readonly optional dracoDecoderPath?: string;

Draco decoder directory handed to the default gltf loader.

fixedHz?
ts
readonly optional fixedHz?: number;

Simulation rate. Defaults to 60.

ktx2TranscoderPath?
ts
readonly optional ktx2TranscoderPath?: string;

Basis transcoder directory handed to the default gltf loader.

loaders?
ts
readonly optional loaders?: Readonly<Record<string, AssetLoader>>;

Asset loaders, replacing the built-in gltf and audio pair.

Adding a type is engine.ctx.assets.registerLoader(...), not this.

manifest?
ts
readonly optional manifest?: string | object | AssetManifest;

The asset manifest: a URL to fetch, or an already-parsed document.

Omit for an engine with an empty registry, which is what the unit tests and the splat viewer use.

maxSubsteps?
ts
readonly optional maxSubsteps?: number;

Most fixed steps one frame may run. Defaults to 5.

modules?
ts
readonly optional modules?: readonly EngineModule[];

Modules to register, in any order; order decides the run order.

renderer?
ts
readonly optional renderer?: EngineRendererOptions;

Renderer options.


DebugOverlay

The debug overlay.

Properties

element
ts
readonly element: HTMLElement | null;

The panel element, or null when there is no DOM to mount into.

stats
ts
readonly stats: FrameStats;

The frame-time window behind the numbers.

visible
ts
readonly visible: boolean;

Whether the panel is currently shown.

Methods

dispose()
ts
dispose(): void;

Remove the panel and the key listener.

Returns

void

sample()
ts
sample(frameMs, nowMs): void;

Record a frame and, at most every intervalMs, redraw.

Parameters
ParameterTypeDescription
frameMsnumberHow long the frame took, in milliseconds.
nowMsnumberCurrent timestamp, in milliseconds.
Returns

void

setVisible()
ts
setVisible(value): void;

Show or hide the panel.

Parameters
ParameterTypeDescription
valuebooleanTrue to show.
Returns

void

toggle()
ts
toggle(): void;

Flip visibility. This is what the hotkey does.

Returns

void


DebugOverlayOptions

Options accepted by createDebugOverlay.

Properties

backendName
ts
readonly backendName: string;

Backend label, for example webgpu or webgl.

container?
ts
readonly optional container?: HTMLElement;

Where to mount the panel. Defaults to document.body.

hotkey?
ts
readonly optional hotkey?: string;

KeyboardEvent.code that toggles visibility. Defaults to F3.

intervalMs?
ts
readonly optional intervalMs?: number;

How often the text is rewritten, in milliseconds. Defaults to 250.

renderer
ts
readonly renderer: WebGPURenderer;

Renderer whose info.render counters are shown.

samples?
ts
readonly optional samples?: number;

Frames in the percentile window. Defaults to 120.

visible?
ts
readonly optional visible?: boolean;

Whether the panel starts visible. Defaults to true.


Engine

A booted engine.

Properties

assets
ts
readonly assets: AssetRegistry;

The asset registry.

camera
ts
readonly camera: PerspectiveCamera;

The camera being rendered from.

ctx
ts
readonly ctx: EngineContext;

The module context, for code that is not a module.

events
ts
readonly events: Events<EngineEventMap>;

The engine event bus.

graph
ts
readonly graph: SceneGraph;

Entity-id to Object3D mapping, rooted in the scene.

loop
ts
readonly loop: FixedLoop;

The fixed-step loop.

modules
ts
readonly modules: ModuleRegistry;

The module registry.

overlay
ts
readonly overlay: DebugOverlay | null;

The debug overlay, when debug was set.

renderer
ts
readonly renderer: WebGPURenderer;

The initialised renderer.

running
ts
readonly running: boolean;

Whether the loop is running.

scene
ts
readonly scene: Scene;

The scene being rendered.

Methods

dispose()
ts
dispose(): Promise<void>;

Stop, dispose every module in reverse order, then the renderer.

Returns

Promise<void>

Resolves once the renderer has released its device.

get()
ts
get<K>(id): EngineServices[K];

Look up a module's service.

Type Parameters
Type Parameter
K extends "physics"
Parameters
ParameterTypeDescription
idKService id, typed through EngineServices.
Returns

EngineServices[K]

The service.

resize()
ts
resize(width, height): void;

Resize the drawing buffer and the camera.

Called automatically by the canvas ResizeObserver; call it yourself only when you manage the canvas size some other way.

Parameters
ParameterTypeDescription
widthnumberCSS width in pixels.
heightnumberCSS height in pixels.
Returns

void

start()
ts
start(): void;

Start the loop.

Returns

void

stop()
ts
stop(): void;

Stop the loop. Modules keep their resources; start resumes.

Returns

void


EngineCaps

What the host turned out to be able to do, decided once after renderer.init().

Properties

characters
ts
readonly characters: boolean;

True when splat characters can run.

Characters need compute shaders and a shared GPUDevice, so this tracks webgpu exactly. Check it before calling createCharacter.

webgpu
ts
readonly webgpu: boolean;

True when the renderer got a real WebGPU backend rather than the WebGL fallback.


EngineConfig

The engine options after defaults were applied.

Properties

antialias
ts
readonly antialias: boolean;

Whether MSAA was requested.

backend
ts
readonly backend: RendererBackend;

Backend that was requested (not necessarily the one that was obtained).

debug
ts
readonly debug: boolean;

Whether the debug overlay was created.

fixedDt
ts
readonly fixedDt: number;

Length of one fixed step, in seconds: 1 / fixedHz.

fixedHz
ts
readonly fixedHz: number;

Simulation rate in hertz.

maxSubsteps
ts
readonly maxSubsteps: number;

Most fixed steps one frame may run.

pixelRatioCap
ts
readonly pixelRatioCap: number;

Upper bound applied to devicePixelRatio.


EngineContext

Everything a module is given at init.

Properties

assets
ts
readonly assets: AssetRegistry;

The asset registry built from the manifest.

camera
ts
readonly camera: PerspectiveCamera;

The camera the engine renders with. Camera rigs drive this.

caps
ts
readonly caps: EngineCaps;

What this host can actually do.

config
ts
readonly config: EngineConfig;

The resolved engine options.

events
ts
readonly events: Events<EngineEventMap>;

The engine event bus.

renderer
ts
readonly renderer: WebGPURenderer;

The initialised renderer. Its backend.device is the one shared GPU device.

scene
ts
readonly scene: Scene;

The scene the engine renders.

time
ts
readonly time: Time;

The engine clock.

Methods

get()
ts
get<K>(id): EngineServices[K];

Look up another module's service.

Only valid after that module's init has run, which order controls.

Type Parameters
Type Parameter
K extends "physics"
Parameters
ParameterTypeDescription
idKService id.
Returns

EngineServices[K]

The service.

registerService()
ts
registerService(id, service): void;

Publish a service under an id, so other modules can get it.

Equivalent to returning the service from init; use this when a module exposes something before it has finished initialising, or exposes nothing but wants to register under a different id.

Parameters
ParameterTypeDescription
idstringService id, matching a key of EngineServices.
serviceobjectThe service object.
Returns

void


EngineEventMap

Events the engine itself publishes.

Other packages add their own by declaration merging, exactly as they do for EngineServices:

ts
declare module '@aosengine/core' {
  interface EngineEventMap {
    'physics:contact': { a: number; b: number };
  }
}

Properties

engine:frame
ts
engine:frame: object;

A frame finished simulating, just before rendering.

alpha
ts
alpha: number;
dtReal
ts
dtReal: number;
frame
ts
frame: number;
substeps
ts
substeps: number;
engine:resize
ts
engine:resize: object;

The drawing buffer changed size.

height
ts
height: number;
width
ts
width: number;
engine:start
ts
engine:start: undefined;

The loop has started.

engine:stop
ts
engine:stop: undefined;

The loop has stopped.


EngineModule

One host subsystem.

init runs once, in order. dispose runs in reverse order and must release everything the module took. The per-frame hooks are optional and are called only on the modules that implement them, so an empty hook costs nothing.

Nothing in beginFrame, fixedUpdate, update or endFrame may allocate: they run at least 60 times a second.

Extended by

Properties

id
ts
readonly id: string;

Unique id. Also the service id when init returns a service.

order?
ts
readonly optional order?: number;

Sort key. Lower runs first; equal keys keep registration order.

Rough convention: input -100, physics 0, gameplay 100, rendering helpers 200.

Methods

beginFrame()?
ts
optional beginFrame(): void;

Run before the frame's fixed steps. Input capture lives here.

Returns

void

dispose()
ts
dispose(): void;

Release everything this module took.

Returns

void

endFrame()?
ts
optional endFrame(): void;

Run after rendering. Input's end-of-frame bookkeeping lives here.

Returns

void

fixedUpdate()?
ts
optional fixedUpdate(dt): void;

Run once per fixed step.

Parameters
ParameterTypeDescription
dtnumberAlways ctx.config.fixedDt.
Returns

void

init()
ts
init(ctx): void | object | Promise<void | object>;

Acquire resources.

Parameters
ParameterTypeDescription
ctxEngineContextThe host surface.
Returns

void | object | Promise<void | object>

Nothing, or the service to publish under id.

update()?
ts
optional update(dt, alpha): void;

Run once per frame, after the fixed steps and before rendering.

Parameters
ParameterTypeDescription
dtnumberClamped wall-clock seconds since the previous frame.
alphanumberInterpolation factor in [0, 1) for smoothing transforms.
Returns

void


EngineRendererOptions

Renderer options accepted by createEngine.

Properties

antialias?
ts
readonly optional antialias?: boolean;

Request MSAA. Defaults to true.

backend?
ts
readonly optional backend?: RendererBackend;

Which backend to target.

auto takes WebGPU when the browser has it and falls back to WebGL otherwise. webgpu refuses to boot without it. webgl forces the fallback, which is useful for reproducing what a WebGL player sees — characters are unavailable there.

pixelRatioCap?
ts
readonly optional pixelRatioCap?: number;

Upper bound on devicePixelRatio. Defaults to 2.


Events

Typed pub/sub over the event map M.

Type Parameters

Type Parameter
M extends EventMap

Methods

clear()
ts
clear(): void;

Drop every handler.

Returns

void

emit()
ts
emit<K>(type, payload): void;

Publish an event.

Type Parameters
Type Parameter
K extends string | number | symbol
Parameters
ParameterTypeDescription
typeKEvent name.
payloadM[K]Payload, matching the map.
Returns

void

listenerCount()
ts
listenerCount(type): number;

How many handlers are subscribed to an event.

Parameters
ParameterTypeDescription
typekeyof MEvent name.
Returns

number

The live listener count.

off()
ts
off<K>(type, listener): void;

Unsubscribe a handler.

Type Parameters
Type Parameter
K extends string | number | symbol
Parameters
ParameterTypeDescription
typeKEvent name.
listenerListener<M[K]>The exact function passed to on.
Returns

void

on()
ts
on<K>(type, listener): () => void;

Subscribe to an event.

Type Parameters
Type Parameter
K extends string | number | symbol
Parameters
ParameterTypeDescription
typeKEvent name.
listenerListener<M[K]>Handler.
Returns

An unsubscribe function, so callers need not keep the reference.

() => void

once()
ts
once<K>(type, listener): () => void;

Subscribe to the next occurrence only.

Type Parameters
Type Parameter
K extends string | number | symbol
Parameters
ParameterTypeDescription
typeKEvent name.
listenerListener<M[K]>Handler.
Returns

An unsubscribe function.

() => void


FirstPersonRig

A first-person camera rig.

Properties

camera
ts
readonly camera: PerspectiveCamera;

The camera being driven.

eyeHeight
ts
eyeHeight: number;

Metres from the pose position up to the eyes. Writable: crouching changes it.

pitch
ts
readonly pitch: number;

Last applied pitch, in radians, after clamping.

yaw
ts
readonly yaw: number;

Last applied yaw, in radians.

Methods

setPose()
ts
setPose(
   position, 
   yaw, 
   pitch
): void;

Place the camera.

position is the body's position — feet, or capsule base — not the eyes; eyeHeight is added to y.

Parameters
ParameterTypeDescription
positionVector3LikeBody position in world space.
yawnumberRotation about world +Y, in radians. 0 looks down −Z.
pitchnumberRotation about the camera's local +X, in radians. Positive looks up.
Returns

void


FirstPersonRigOptions

Options accepted by createFirstPersonRig.

Properties

camera
ts
readonly camera: PerspectiveCamera;

The camera to drive.

eyeHeight?
ts
readonly optional eyeHeight?: number;

Metres from the given position up to the eyes. Defaults to 1.7.

maxPitch?
ts
readonly optional maxPitch?: number;

Pitch is clamped to plus or minus this, in radians.


FixedLoop

A driven fixed-step accumulator.

Properties

accumulator
ts
readonly accumulator: number;

Unconsumed simulation time, always in [0, fixedDt) after a step.

alpha
ts
readonly alpha: number;

Interpolation factor for the last frame, in [0, 1).

fixedDt
ts
readonly fixedDt: number;

Length of one fixed step, in seconds.

frame
ts
readonly frame: number;

Frames stepped so far.

maxSubsteps
ts
readonly maxSubsteps: number;

Most fixed steps one frame may run.

Methods

reset()
ts
reset(): void;

Forget the accumulator and the baseline timestamp.

Call after a long pause (tab hidden, breakpoint, level load) so the next step starts clean instead of clamping.

Returns

void

step()
ts
step(nowMs): FrameTiming;

Advance the loop to nowMs.

The very first call only establishes the baseline: dtReal is 0 and no fixed step runs, so a slow boot cannot manufacture a burst of simulation.

Parameters
ParameterTypeDescription
nowMsnumberA monotonic timestamp in milliseconds, usually from rAF.
Returns

FrameTiming

What this frame did.


FixedLoopOptions

Options accepted by createFixedLoop.

Properties

fixedDt?
ts
readonly optional fixedDt?: number;

Length of one fixed step, in seconds. Defaults to 1/60.

fixedUpdate?
ts
readonly optional fixedUpdate?: (dt) => void;

Run once per fixed step, always with exactly fixedDt.

Parameters
ParameterTypeDescription
dtnumberAlways fixedDt.
Returns

void

maxSubsteps?
ts
readonly optional maxSubsteps?: number;

Most fixed steps one frame may run. Defaults to 5.

render?
ts
readonly optional render?: (alpha) => void;

Run once per frame, last.

Parameters
ParameterTypeDescription
alphanumberInterpolation factor in [0, 1).
Returns

void

update?
ts
readonly optional update?: (dtReal, alpha) => void;

Run once per frame, after the fixed steps.

Parameters
ParameterTypeDescription
dtRealnumberClamped wall-clock seconds since the previous frame.
alphanumberInterpolation factor in [0, 1).
Returns

void


FrameStats

A rolling window of frame durations.

Properties

capacity
ts
readonly capacity: number;

Frames the window holds.

count
ts
readonly count: number;

Samples recorded so far, capped at capacity.

fps
ts
readonly fps: number;

Smoothed frames per second.

last
ts
readonly last: number;

Duration of the most recent frame, in milliseconds.

Methods

percentile()
ts
percentile(p): number;

A percentile of the window.

Parameters
ParameterTypeDescription
pnumberPercentile in [0, 1]; 0.5 is the median.
Returns

number

The frame time in milliseconds, or 0 before any sample.

push()
ts
push(frameMs): void;

Record one frame.

Parameters
ParameterTypeDescription
frameMsnumberHow long the frame took, in milliseconds.
Returns

void

reset()
ts
reset(): void;

Forget every sample.

Returns

void


FrameTiming

What a call to FixedLoop.step did.

Properties

alpha
ts
readonly alpha: number;

Interpolation factor for rendering, always in [0, 1).

clamped
ts
readonly clamped: boolean;

True when time had to be thrown away to avoid a death spiral.

dtReal
ts
readonly dtReal: number;

Wall-clock seconds since the previous frame, after clamping.

rawDt
ts
readonly rawDt: number;

Wall-clock seconds since the previous frame, before clamping.

substeps
ts
readonly substeps: number;

Fixed steps run this frame, 0 to maxSubsteps.


ModuleRegistry

Holds modules, orders them, initialises them and takes them down again.

Properties

beginFrameHooks
ts
readonly beginFrameHooks: readonly EngineModule[];

Modules implementing beginFrame, in run order.

endFrameHooks
ts
readonly endFrameHooks: readonly EngineModule[];

Modules implementing endFrame, in run order.

fixedUpdateHooks
ts
readonly fixedUpdateHooks: readonly EngineModule[];

Modules implementing fixedUpdate, in run order.

modules
ts
readonly modules: readonly EngineModule[];

Registered modules in run order.

updateHooks
ts
readonly updateHooks: readonly EngineModule[];

Modules implementing update, in run order.

Methods

disposeAll()
ts
disposeAll(): void;

Dispose every initialised module in reverse order.

A throwing dispose is collected and rethrown at the end, so one bad module cannot strand the others.

Returns

void

get()
ts
get<K>(id): EngineServices[K];

Look up a service, typed through EngineServices.

Type Parameters
Type Parameter
K extends "physics"
Parameters
ParameterTypeDescription
idKService id.
Returns

EngineServices[K]

The service.

has()
ts
has(id): boolean;

Whether a service is registered under an id.

Parameters
ParameterTypeDescription
idstringService id.
Returns

boolean

True when get would succeed.

initAll()
ts
initAll(ctx): Promise<void>;

Initialise every module in order, awaiting each one.

Modules are initialised sequentially, not in parallel, because order is a dependency order: a module may ctx.get anything registered before it.

Parameters
ParameterTypeDescription
ctxEngineContextThe host surface.
Returns

Promise<void>

Resolves once every module has initialised.

register()
ts
register(module): void;

Add a module. Must happen before ModuleRegistry.initAll.

Parameters
ParameterTypeDescription
moduleEngineModuleThe module.
Returns

void

registerService()
ts
registerService(id, service): void;

Publish a service under an id.

Parameters
ParameterTypeDescription
idstringService id.
serviceobjectThe service object.
Returns

void

tryGet()
ts
tryGet(id): unknown;

Look up a service without the typed table.

The escape hatch for code that does not know the id at compile time, and for core itself, which must not know what modules exist.

Parameters
ParameterTypeDescription
idstringService id.
Returns

unknown

The service, or undefined when nothing is registered.


MutableTime

The engine's own handle on the clock: the same object, writable.

Extends

Properties

elapsed
ts
elapsed: number;

Scaled seconds simulated since start().

Overrides

Time.elapsed

fixedDt
ts
fixedDt: number;

Length of one fixed step, in seconds.

Overrides

Time.fixedDt

frame
ts
frame: number;

Frames rendered since start(), starting at 0.

Overrides

Time.frame

now
ts
now: number;

performance.now() of the current frame, in milliseconds.

Overrides

Time.now

timeScale
ts
timeScale: number;

Simulation speed multiplier. 0 pauses, 0.5 is half speed.

Inherited from

Time.timeScale


PatchableAdapterPrototype

The parts of GPUAdapter the patch touches.

Methods

requestDevice()
ts
requestDevice(descriptor?): Promise<GPUDevice>;

The method being wrapped.

Parameters
ParameterTypeDescription
descriptor?GPUDeviceDescriptorDevice descriptor, as the caller wrote it.
Returns

Promise<GPUDevice>

The requested device.


ThirdPersonRig

A third-person orbit camera with a collision-aware spring arm.

Properties

actualDistance
ts
readonly actualDistance: number;

Arm length actually used last frame, after collision.

camera
ts
readonly camera: PerspectiveCamera;

The camera being driven.

collisionProbe
ts
collisionProbe: CollisionProbe | null;

Obstacle probe. Assign to swap it at runtime, or null to disable collision.

distance
ts
readonly distance: number;

Requested arm length, before collision.

pitch
ts
readonly pitch: number;

Last applied pitch, in radians, after clamping.

pivotHeight
ts
pivotHeight: number;

Height of the orbit pivot above the target.

yaw
ts
readonly yaw: number;

Last applied yaw, in radians.

Methods

apply()
ts
apply(): void;

Re-run the probe and reposition the camera with the current target and orbit.

Both setters call this; you only need it when the world changed but the inputs did not.

Returns

void

setOrbit()
ts
setOrbit(
   yaw, 
   pitch, 
   distance
): void;

Set the orbit and apply the result.

Parameters
ParameterTypeDescription
yawnumberRotation about world +Y, in radians. 0 puts the camera on +Z.
pitchnumberRotation above the horizon, in radians. Positive looks down at the target.
distancenumberRequested arm length, in metres.
Returns

void

setTarget()
ts
setTarget(position): void;

Point the rig at a target and apply the result.

Parameters
ParameterTypeDescription
positionVector3LikeThe target's world position, at its feet.
Returns

void


ThirdPersonRigOptions

Options accepted by createThirdPersonRig.

Properties

camera
ts
readonly camera: PerspectiveCamera;

The camera to drive.

collisionPadding?
ts
readonly optional collisionPadding?: number;

Gap left between camera and obstacle. Defaults to 0.15.

collisionProbe?
ts
readonly optional collisionProbe?: CollisionProbe;

Obstacle probe. Omit for a rig that never collides.

maxPitch?
ts
readonly optional maxPitch?: number;

Pitch is clamped to plus or minus this, in radians.

minDistance?
ts
readonly optional minDistance?: number;

Closest the arm may pull in. Defaults to 0.4.

pivotHeight?
ts
readonly optional pivotHeight?: number;

Height of the orbit pivot above the target position. Defaults to 1.5.


Time

Read-only view of the engine clock, as modules and game code see it.

Extended by

Properties

elapsed
ts
readonly elapsed: number;

Scaled seconds simulated since start().

fixedDt
ts
readonly fixedDt: number;

Length of one fixed step, in seconds.

frame
ts
readonly frame: number;

Frames rendered since start(), starting at 0.

now
ts
readonly now: number;

performance.now() of the current frame, in milliseconds.

timeScale
ts
timeScale: number;

Simulation speed multiplier. 0 pauses, 0.5 is half speed.


Vector3Like

Anything with x, y and z. Avoids allocating a Vector3 per call.

Properties

x
ts
readonly x: number;

X component.

y
ts
readonly y: number;

Y component.

z
ts
readonly z: number;

Z component.


WebGPUPatchOptions

Options accepted by initWebGPUPatches.

Properties

maxStorageBuffersPerShaderStage?
ts
readonly optional maxStorageBuffersPerShaderStage?: number;

Storage buffers per shader stage to ask for.

The patch requests min(this, adapter.limits.maxStorageBuffersPerShaderStage), so asking for more than the adapter has is harmless. Defaults to DEFAULT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE.

target?
ts
readonly optional target?: PatchableAdapterPrototype;

Prototype to patch. Defaults to the global GPUAdapter.prototype.

Tests pass a fake here; production never sets it.

timestampQuery?
ts
readonly optional timestampQuery?: boolean;

Also request the timestamp-query feature when the adapter has it.

Needed to time GPU passes in the debug overlay and the benchmarks. Off by default, because the feature has a cost.

Type Aliases

CollisionProbe

ts
type CollisionProbe = (from, to) => number | null;

Asks how far a ray gets before it hits something.

Parameters

ParameterTypeDescription
fromVector3LikeStart of the ray, the orbit pivot.
toVector3LikeWhere the camera would like to be.

Returns

number | null

Distance from from to the hit, in metres, or null for a clear line.


EventMap

ts
type EventMap = object;

Shape of an event map: an interface mapping event name to payload type.

Deliberately object rather than Record<string, unknown>: interfaces have no implicit index signature, and the whole point of EngineEventMap is that packages declaration-merge into it.


Listener

ts
type Listener<T> = (payload) => void;

A handler for one event.

Type Parameters

Type Parameter
T

Parameters

ParameterType
payloadT

Returns

void


RendererBackend

ts
type RendererBackend = "auto" | "webgpu" | "webgl";

Which three.js backend the renderer should target.

Variables

DEFAULT_COLLISION_PADDING

ts
const DEFAULT_COLLISION_PADDING: 0.15 = 0.15;

Default gap left between the camera and whatever the probe hit, in metres.


DEFAULT_EYE_HEIGHT

ts
const DEFAULT_EYE_HEIGHT: 1.7 = 1.7;

Default eye height above the feet, in metres.


DEFAULT_FIXED_DT

ts
const DEFAULT_FIXED_DT: number;

Default simulation rate: 60 Hz.


DEFAULT_MAX_PITCH

ts
const DEFAULT_MAX_PITCH: number;

Default pitch limit: just short of straight up or down, in radians.


DEFAULT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE

ts
const DEFAULT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE: 10 = 10;

Storage buffers per shader stage the engine asks for. The WebGPU default is 8.


DEFAULT_MAX_SUBSTEPS

ts
const DEFAULT_MAX_SUBSTEPS: 5 = 5;

Default cap on fixed steps per frame.


DEFAULT_MIN_DISTANCE

ts
const DEFAULT_MIN_DISTANCE: 0.4 = 0.4;

Default closest the arm may pull in, in metres.


DEFAULT_OVERLAY_HOTKEY

ts
const DEFAULT_OVERLAY_HOTKEY: "F3" = 'F3';

KeyboardEvent.code that toggles the panel.


DEFAULT_OVERLAY_INTERVAL_MS

ts
const DEFAULT_OVERLAY_INTERVAL_MS: 250 = 250;

How often the panel's text is rewritten, in milliseconds.


DEFAULT_PIVOT_HEIGHT

ts
const DEFAULT_PIVOT_HEIGHT: 1.5 = 1.5;

Default height of the orbit pivot above the target, in metres.


DEFAULT_PIXEL_RATIO_CAP

ts
const DEFAULT_PIXEL_RATIO_CAP: 2 = 2;

Default upper bound on devicePixelRatio.


DEFAULT_SAMPLE_COUNT

ts
const DEFAULT_SAMPLE_COUNT: 120 = 120;

Frames kept in the window by default: two seconds at 60 Hz.


DEFAULT_TRANSFORM_CAPACITY

ts
const DEFAULT_TRANSFORM_CAPACITY: 256 = 256;

Default number of entity slots a new store reserves.


NO_ENTITY

ts
const NO_ENTITY: 0 = 0;

The entity id that means "no entity"; also the id of the root group.


PACKAGE

ts
const PACKAGE: "@aosengine/core";

Package identity marker.

Example

ts
import { PACKAGE } from '@aosengine/core';

console.log(PACKAGE); // '@aosengine/core'

Functions

createDebugOverlay()

ts
function createDebugOverlay(options): DebugOverlay;

Build the debug overlay.

On a host with no document — Node, a worker, a test — this returns a working overlay whose element is null: the statistics still accumulate and can be read, nothing is mounted, and nothing throws.

Parameters

ParameterTypeDescription
optionsDebugOverlayOptionsRenderer, backend label and panel settings.

Returns

DebugOverlay

The overlay.

Example

ts
import { createDebugOverlay } from '@aosengine/core';
import { WebGPURenderer } from 'three/webgpu';

const renderer = new WebGPURenderer({ canvas: document.createElement('canvas') });
const overlay = createDebugOverlay({ renderer, backendName: 'webgpu' });
overlay.sample(16.6, performance.now()); // call once per frame

createEngine()

ts
function createEngine(options): Promise<Engine>;

Boot an engine around a canvas.

Parameters

ParameterTypeDescription
optionsCreateEngineOptionsCanvas, manifest, modules, loop rate and renderer settings.

Returns

Promise<Engine>

The booted engine. The loop is not running; call start().

Example

ts
import { createEngine } from '@aosengine/core';

const canvas = document.querySelector('canvas')!;
const engine = await createEngine({
  canvas,
  manifest: '/assets/assets.json',
  modules: [],
  fixedHz: 60,
  renderer: { backend: 'auto' },
  debug: import.meta.env?.DEV === true,
});
engine.start();

createEvents()

ts
function createEvents<M>(): Events<M>;

Build a typed event bus.

The type parameter is the event map. Packages extend the engine's map by declaration-merging into EngineEventMap; standalone buses pass their own.

Type Parameters

Type Parameter
M extends object

Returns

Events<M>

An empty bus.

Example

ts
import { createEvents } from '@aosengine/core';

const events = createEvents<{ hit: { damage: number } }>();
const off = events.on('hit', (e) => console.log(e.damage));
events.emit('hit', { damage: 7 }); // logs 7
off();

createFirstPersonRig()

ts
function createFirstPersonRig(options): FirstPersonRig;

Build a first-person rig.

The camera's Euler order is set to YXZ once, which is what makes yaw and pitch independent: yaw always turns about world up, pitch always about the camera's own right, and there is no roll.

Parameters

ParameterTypeDescription
optionsFirstPersonRigOptionsCamera, eye height and pitch limit.

Returns

FirstPersonRig

The rig.

Example

ts
import { createFirstPersonRig } from '@aosengine/core';
import { PerspectiveCamera } from 'three/webgpu';

const rig = createFirstPersonRig({ camera: new PerspectiveCamera(), eyeHeight: 1.7 });
rig.setPose({ x: 0, y: 0, z: 0 }, Math.PI, 0);
console.log(rig.camera.position.y); // 1.7

createFixedLoop()

ts
function createFixedLoop(options?): FixedLoop;

Build a fixed-step loop.

The accumulator drains at most maxSubsteps times per frame. Anything left over is thrown away rather than carried, because carrying it is what turns a slow frame into a spiral of death: each frame owes more simulation than the last and the game never catches up. clamped in the returned FrameTiming says when that happened.

Parameters

ParameterTypeDescription
optionsFixedLoopOptionsStep length, substep cap and the three callbacks.

Returns

FixedLoop

The loop. Nothing runs until you call step.

Example

ts
import { createFixedLoop } from '@aosengine/core';

let ticks = 0;
const loop = createFixedLoop({ fixedUpdate: () => { ticks += 1; } });
loop.step(0);      // baseline: no fixed steps
loop.step(1000/30); // 33.3 ms buys two 60 Hz steps
console.log(ticks); // 2

createFrameStats()

ts
function createFrameStats(capacity?): FrameStats;

Build a frame-time window.

Parameters

ParameterTypeDefault valueDescription
capacitynumberDEFAULT_SAMPLE_COUNTFrames to keep. Defaults to 120.

Returns

FrameStats

An empty window.

Example

ts
import { createFrameStats } from '@aosengine/core';

const stats = createFrameStats(4);
for (const ms of [10, 20, 30, 40]) stats.push(ms);
console.log(stats.percentile(0.5)); // 20

createModuleRegistry()

ts
function createModuleRegistry(): ModuleRegistry;

Build a module registry.

Returns

ModuleRegistry

An empty registry.

Example

ts
import { createModuleRegistry } from '@aosengine/core';

const registry = createModuleRegistry();
registry.register({ id: 'clock', order: -10, init: () => ({ t: 0 }), dispose: () => {} });
console.log(registry.modules[0]?.id); // 'clock'

createThirdPersonRig()

ts
function createThirdPersonRig(options): ThirdPersonRig;

Build a third-person rig.

Parameters

ParameterTypeDescription
optionsThirdPersonRigOptionsCamera, pivot height, arm limits and the collision probe.

Returns

ThirdPersonRig

The rig.

Example

ts
import { createThirdPersonRig } from '@aosengine/core';
import { PerspectiveCamera } from 'three/webgpu';

const rig = createThirdPersonRig({ camera: new PerspectiveCamera(), pivotHeight: 1.5 });
rig.setTarget({ x: 0, y: 0, z: 0 });
rig.setOrbit(0, 0, 4);
console.log(rig.camera.position.z); // 4

createTime()

ts
function createTime(fixedDt): MutableTime;

Build an engine clock.

Parameters

ParameterTypeDescription
fixedDtnumberLength of one fixed step, in seconds.

Returns

MutableTime

A clock at frame 0, elapsed 0, timeScale 1.

Example

ts
import { createTime } from '@aosengine/core';

const time = createTime(1 / 60);
time.timeScale = 0.5; // slow motion
console.log(time.fixedDt); // 0.016666…

initWebGPUPatches()

ts
function initWebGPUPatches(options?): boolean;

Patch GPUAdapter.prototype.requestDevice so every device the page creates clears the engine's limits.

Idempotent. Calling it again does not wrap the method twice; it raises the requested limits if the new call asks for more. Safe to call on a host with no WebGPU at all, where it does nothing and returns false.

Must run before renderer.init(), and before anything else creates a device.

Parameters

ParameterTypeDescription
optionsWebGPUPatchOptionsLimits to request, and the prototype to patch.

Returns

boolean

True when the patch is installed, false when the host has no WebGPU.

Example

ts
import { initWebGPUPatches } from '@aosengine/core';
import { WebGPURenderer } from 'three/webgpu';

initWebGPUPatches({ maxStorageBuffersPerShaderStage: 10 });
const renderer = new WebGPURenderer({ canvas: document.createElement('canvas') });
await renderer.init();

isWebGPUBackend()

ts
function isWebGPUBackend(renderer): boolean;

Whether a renderer ended up on a real WebGPU backend.

three sets isWebGPUBackend on WebGPUBackend and isWebGLBackend on the fallback, but neither class is exported from three/webgpu, so this is a duck-type check rather than an instanceof.

Parameters

ParameterTypeDescription
rendererWebGPURendererAn initialised renderer.

Returns

boolean

True on WebGPU, false on the WebGL fallback.

Example

ts
import { isWebGPUBackend } from '@aosengine/core';
import { WebGPURenderer } from 'three/webgpu';

const renderer = new WebGPURenderer({ canvas: document.createElement('canvas') });
await renderer.init();
console.log(isWebGPUBackend(renderer));

isWebGPUPatched()

ts
function isWebGPUPatched(target?): boolean;

Whether a prototype already carries the patch.

Parameters

ParameterTypeDescription
target?PatchableAdapterPrototypePrototype to check. Defaults to the global GPUAdapter.prototype.

Returns

boolean

True when initWebGPUPatches has run against it.

Example

ts
import { initWebGPUPatches, isWebGPUPatched } from '@aosengine/core';

initWebGPUPatches();
console.log(isWebGPUPatched()); // true in a browser with WebGPU

resolveEngineConfig()

ts
function resolveEngineConfig(options?): EngineConfig;

Apply the documented defaults to the engine options.

Exported for the unit tests; createEngine is the real entry point.

Parameters

ParameterTypeDescription
optionsOmit<CreateEngineOptions, "canvas">Options as the caller wrote them.

Returns

EngineConfig

The resolved configuration.

Example

ts
import { resolveEngineConfig } from '@aosengine/core';

const config = resolveEngineConfig({ fixedHz: 120 });
console.log(config.fixedDt); // 0.008333…