Camera Module API Reference
This reference tracks the real exports from src/camera/. All maths are based on gl-matrix (vec3, vec2, quat, mat3, mat4).
Exports
import {
type Camera,
PerspectiveCamera,
PerspectiveProjection,
CameraAdapter,
world2view,
buildProj,
deg2rad,
focal2fov,
fov2focal,
Aabb,
VIEWPORT_Y_FLIP,
} from 'src/camera';
Interface: Camera
interface Camera {
viewMatrix(): mat4;
projMatrix(): mat4;
position(): vec3;
frustumPlanes(): {
near: Float32Array;
far: Float32Array;
left: Float32Array;
right: Float32Array;
top: Float32Array;
bottom: Float32Array;
};
}
Any camera passed to preprocess or renderer must implement this interface. A few notes:
- Matrices must be column-major and ready for GPU upload.
- position() returns a clone (mutating the result has no effect on the camera).
- frustumPlanes() returns normalized [A, B, C, D] planes suitable for distance tests.
Class: PerspectiveProjection
class PerspectiveProjection {
constructor(
viewport: vec2 | [number, number],
fov: vec2 | [number, number], // radians [fovx, fovy]
znear: number,
zfar: number,
);
fovx: number;
fovy: number;
znear: number;
zfar: number;
clone(): PerspectiveProjection;
resize(viewport: vec2 | [number, number]): void;
projectionMatrix(): mat4;
focal(viewport: vec2 | [number, number]): [number, number];
lerp(other: PerspectiveProjection, t: number): PerspectiveProjection;
}
Behaviour
resize()preserves the original relationship between viewport aspect and FOV aspect via an internalfov2viewRatio.projectionMatrix()is a thin wrapper overbuildProj(znear, zfar, fovx, fovy)(WebGPU depth range[0, 1]).focal()returns per-axis focal lengths in pixels (used by preprocess).lerp()interpolates FOV and near/far planes for smooth camera animations.
Class: PerspectiveCamera
class PerspectiveCamera implements Camera {
constructor(position: vec3, rotation: quat, projection: PerspectiveProjection);
static default(): PerspectiveCamera;
positionV: vec3; // world-space position (use clones when assigning)
rotationQ: quat; // world->camera quaternion
projection: PerspectiveProjection;
fitNearFar(aabb: Aabb): void;
viewMatrix(): mat4;
projMatrix(): mat4;
position(): vec3;
frustumPlanes(): {
near: Float32Array;
far: Float32Array;
left: Float32Array;
right: Float32Array;
top: Float32Array;
bottom: Float32Array;
};
}
Notes
fitNearFar(aabb)adjustsznear/zfarbased on the distance between the camera and the AABB centre, enforcing a minimum ratio (zfar / 1000).viewMatrix()convertsrotationQinto a 3×3 matrix and callsworld2view(world→camera transform).frustumPlanes()multipliesprojMatrix * viewMatrixand extracts Gribb–Hartmann planes; normals are normalized.static default()creates a camera at(0,0,-1)with 45° FOV and[0.1, 100]depth range.
Class: CameraAdapter
Allows Three.js cameras to drive the core pipeline.
class CameraAdapter implements Camera {
update(camera: THREE.PerspectiveCamera, viewport: [number, number]): void;
viewMatrix(): mat4;
projMatrix(): mat4;
position(): Float32Array;
frustumPlanes(): Float32Array; // placeholder (24 values)
projection: { focal(viewport?: [number, number]): [number, number] };
transposeRotation: boolean;
flipProjY: boolean;
flipProjX: boolean;
}
Behaviour
update()copies Three’s matrices, premultiplies bydiag(-1, 1, -1, 1)so view/projection match the core convention, compensates for the Y flip performed during preprocess packing, and computes per-axis focal lengths.- After calling
update, the adapter satisfies theCamerainterface and can be passed directly todispatchModelor renderer code.
Functions
world2view(R_wc: mat3, C: vec3): mat4
Builds a world→camera transform from a rotation matrix (world→camera) and camera position.
buildProj(znear: number, zfar: number, fovx: number, fovy: number): mat4
Returns a column-major perspective matrix compatible with WebGPU’s clip-space conventions.
Math helpers (re-exported)
deg2rad(degrees: number): numberfov2focal(fovRadians: number, pixels: number): numberfocal2fov(focalPixels: number, pixels: number): numberAabb(axis-aligned bounding box utility used byfitNearFar).VIEWPORT_Y_FLIP�?mat4constant that multiplies Y by �? (used where a single flip is required).
Example
import { PerspectiveCamera, PerspectiveProjection, deg2rad } from 'src/camera';
const projection = new PerspectiveProjection(
[1920, 1080],
[deg2rad(65), deg2rad(45)],
0.1,
500,
);
const camera = new PerspectiveCamera(vec3.fromValues(0, 2, -4), quat.create(), projection);
camera.fitNearFar(pointCloud.bbox);
const view = camera.viewMatrix();
const proj = camera.projMatrix();
const planes = camera.frustumPlanes();
Using Three.js: