LeCodesdocs

Camera

The scene camera, reached at scene.camera. It's a Node, so the full transform surface works — position, eulerAngles, lookAt, forward. On top of that it exposes projection reads and screen→world ray helpers for picking.

You never construct one: every Scene creates its own camera (overlays share the parent's). In an ARScene the camera is driven by device tracking — read it, don't place it.

At a glance

TypeScript
scene.camera.position = [0, 2, 4]
scene.camera.lookAt([0, 0.5, 0])

scene.addEventListener('touchstart', ev => {
  const ray = scene.camera.getRay(ev.clientX, ev.clientY)
  const hit = Physics.raycast(ray.origin, ray.dir)
  if (hit) console.log('tapped', hit.node?.name)
})

Projection

TypeScript
camera.fov               // vertical field of view, DEGREES — settable (default 60)
camera.near              // near clip distance, settable (default 0.01)
camera.far               // far clip distance = view range, settable (default 1000)
camera.setProjection({ fov: 45, far: 5000 })   // any subset, one call

camera.horizontalFov     // horizontal field of view, degrees (read-only, derived from fov + aspect)
camera.displaySize       // [width, height] of the 3D viewport, px (read-only)
camera.projectionMatrix  // Float32Array(16), live — the host updates it in place on resize/fov change

The aspect ratio stays host-owned: you set the lens, the host keeps it across every resize. Nothing nearer than near or further than far draws, so far is the scene's view range — raise it for open worlds. Shadows keep their own (shorter) range, so a long view distance costs nothing in shadow sharpness.

In a scene file the same three live on the camera block:

TypeScript
camera: { position: [0, 6, 12], target: [0, 0, 0], fov: 45 }   // top-level block
nodes: { cam: { camera: { fov: 45, far: 5000 } } }             // …or the camera NODE (it wins)

Hosts that predate the projection call keep the fixed defaults — setting it there is inert, not an error. See docs/parity/MATRIX.md (gl-camera-projection).

Screen → world rays

TypeScript
camera.getViewDirection(screenX, screenY): Vec3   // world-space ray direction through a screen point
camera.getRay(screenX, screenY): Ray              // origin = camera.worldPosition, dir = view direction

Screen coordinates are logical px — the same space as ev.clientX / ev.clientY. getRay pairs directly with Physics.raycast for tap-picking; Ray is documented in ray-plane-noise.

Note

there is no worldToScreen helper — the inverse projection is only available raw, via projectionMatrix + the camera's worldMatrix.

Pitfalls

TypeScript
// ✗ moving the camera in an ARScene — tracking overwrites it every frame
arScene.camera.position = [0, 2, 4]
// ✓ move the WORLD instead: parent content under scene.root and place that

See also

  • Scene — where the camera comes from; overlays share it
  • Node — the inherited transform surface (position, lookAt, forward)
  • 3D physics & shapes — raycasting the rays you build here
  • Ray, Plane, Noise — the Ray returned by getRay