Controls Module API Reference
This reference mirrors the TypeScript exports under src/controls/. All math uses gl-matrix data types (vec2, vec3, quat).
Interfaces
IController
interface IController {
update(camera: PerspectiveCamera, deltaTime: number): void;
processKeyboard(code: string, pressed: boolean): boolean;
processMouse(dx: number, dy: number): void;
processScroll(delta: number): void;
leftMousePressed: boolean;
rightMousePressed: boolean;
userInput: boolean;
resetOrientation?(): void;
getControllerType(): 'orbit' | 'fps';
}
Both CameraController (orbit) and FPSController implement this contract so the app can swap controllers at runtime.
Classes
CameraController
Orbit controller used by default.
class CameraController implements IController {
constructor(speed = 0.2, sensitivity = 0.1);
center: vec3;
up: vec3 | null;
amount: vec3; // reserved for keyboard motion
shift: vec2; // right-click pan accumulator
rotation: vec3; // yaw/pitch/roll accumulators
scroll: number; // logarithmic zoom accumulator
speed: number;
sensitivity: number;
leftMousePressed: boolean;
rightMousePressed: boolean;
altPressed: boolean;
userInput: boolean;
resetUp(u?: vec3): void;
processKeyboard(code: string, pressed: boolean): boolean;
processMouse(dx: number, dy: number): void;
processScroll(delta: number): void;
update(camera: PerspectiveCamera, deltaTime: number): void;
resetOrientation(): void;
getControllerType(): 'orbit';
}
resetUp(u)sets the orbit reference up vector (WORLD_UPby default).processKeyboard/processMouse/processScrollcall the helpers frominput.tsand setuserInput = truewhen handled.updateruns the orbit pipeline described in the architecture doc and updatescamera.positionV/camera.rotationQ.
FPSController
WASD + mouse-look controller (experimental but exported).
class FPSController implements IController {
constructor(moveSpeed?, rotateSpeed?, scrollSpeed?, moveInertia?, rotateInertia?);
moveSpeed: number;
rotateSpeed: number;
scrollSpeed: number;
moveInertia: number;
rotateInertia: number;
flyMode: boolean;
enable: boolean;
leftMousePressed: boolean;
rightMousePressed: boolean;
userInput: boolean;
processKeyboard(code: string, pressed: boolean): boolean;
processMouse(dx: number, dy: number): void;
processScroll(delta: number): void;
update(camera: PerspectiveCamera, deltaTime: number): void;
resetOrientation(): void;
getOrientation(): { yaw: number; pitch: number };
setOrientation(yaw: number, pitch: number): void;
setFlyMode(enabled: boolean): void;
getControllerType(): 'fps';
}
FPSController listens for document-level key events (in its constructor) and keeps yaw/pitch angles plus velocity vectors for inertia. flyMode = false constrains movement to the XZ plane.
Input helpers (input.ts)
processKeyboardInput(code, pressed, amount, rotation, sensitivity)
Updates amount (vec3) and rotation (vec3) arrays in place. Handles KeyW/A/S/D, Space, ShiftLeft, KeyQ, KeyE. Returns true when a key is recognized.
processMouseInput(dx, dy, leftPressed, rightPressed, rotation, shift)
Adds mouse deltas to rotation (left button) or shift (right button). Returns true if any button was active.
processScrollInput(delta)
Scales scroll wheel deltas (default multiplier 3) and returns the value for accumulation.
Orbit math (orbit.ts)
Constants
WORLD_UP = vec3(0, 1, 0)MIN_POLE_ANGLE = 5°MIN_DISTANCE = 0.1MAX_DISTANCE = 1000EPS = 1e-6
Functions
lookAtW2C(forwardWorld: vec3, upWorld: vec3): quat;
projectOntoPlaneNormed(v: vec3, n: vec3, fallback: vec3): vec3;
calculateOrbitBasis(cameraPos: vec3, center: vec3, orbitUp: vec3)
=> { forward: vec3, right: vec3, yawAxis: vec3 };
applyDistanceScaling(cameraPos, center, scroll, deltaTime, speed): number;
applyPanning(center, shift, right, yawAxis, deltaTime, speed, distance): void;
applyRotation(forward, right, yawAxis, yaw, pitch, roll)
=> { forward: vec3, right: vec3, yawAxis: vec3 };
applyDecay(rotation: vec3, shift: vec2, scroll: number, deltaTime: number)
=> { rotation: vec3, shift: vec2, scroll: number };
These functions are stateless; controllers pass in temporary vectors and reuse the results.
Usage snippet
import { CameraController } from 'src/controls';
import { PerspectiveCamera } from 'src/camera';
const controller = new CameraController(0.25, 0.12);
const camera = PerspectiveCamera.default();
function frame(dt: number) {
controller.update(camera, dt);
renderer.prepareMulti(encoder, queue, [pointCloud], { camera, viewport: [w, h] });
}
Mouse/keyboard wiring (simplified):
window.addEventListener('keydown', (e) => controller.processKeyboard(e.code, true));
window.addEventListener('keyup', (e) => controller.processKeyboard(e.code, false));
canvas.addEventListener('mousemove', (e) => controller.processMouse(e.movementX, e.movementY));
canvas.addEventListener('wheel', (e) => controller.processScroll(e.deltaY));
See fps-controller.ts for an alternative setup with inertia and 6DoF flight controls.