Camera Types
Viewer Camera
The viewer camera is the camera the user sees through. It is owned by React Three Fiber and can be controlled with tools such asOrbitControls.
MuJoCo Cameras
MuJoCo cameras are declared in MJCF. They move with their parent body and are exposed through MuJoCo camera state such ascam_xpos and cam_xmat.
Use cameraName when you want a frame from an MJCF <camera>:
mujocoCameraCompatibility applies MuJoCo camera metadata such as resolution,
field of view, clipping, and intrinsics when the WASM model exposes them.
Mounted Capture Poses
For policy or dataset streams, a camera can also be resolved from a MuJoCo site or body. This is useful when a robot model exposes optical frames as sites instead of MJCF cameras.Explicit Capture Poses
Useposition with lookAt when the camera is synthetic and not part of the
MuJoCo model.
<camera>, and it is not automatically visible in the scene.
Virtual Debug Cameras
virtualCameras on <Debug> draws a marker and frustum for synthetic camera
poses. This helps you line up explicit policy or offscreen render viewpoints
without adding extra MJCF cameras.
Output Modes: Snapshot, Live Stream, Tensor
Any camera pose above (MJCF camera, mounted site/body, or explicit pose) can be turned into three different outputs. Pick the output by what consumes it.
The snapshot helpers (
captureCameraFrame, useCameraFrameCapture,
usePolicyCameraFrames, recordMountedCameraFrameSequence) all produce a data
URL or Blob — they encode a PNG/JPEG on every call. That is the right tool for
a download or a single saved frame, but too slow for live preview or per-step
inference. For those, use the live-stream and tensor APIs below, which read
pixels straight off the GPU.
Live Camera Streams
To show a live camera feed on screen, render the scene from a MuJoCo camera into a<canvas> every frame — no PNG round-trip.
For a camera tile embedded in HTML UI (a panel, sidebar, or overlay), use
useCameraStream. Put the <canvas> anywhere in the DOM and call the hook
inside <MujocoCanvas> with a ref to it:
useCameraStream renders offscreen and blits into the canvas, so it composites
normally in the DOM (including inside opaque panels) and does not take over
the render loop. It uses the async capture path, so Gaussian-splat environments
render through their dedicated capture renderer — streaming a splat scene at full
rate does not disturb the main view’s splat sort. Pass fps to cap the update
rate, or paused to freeze it.
For a transparent picture-in-picture overlay on a full-bleed canvas, use
<CameraView> / useCameraViewport, which render the camera into a
gl.scissor region tracking a DOM element:
<CameraView> is cheaper (it scissors into the main canvas instead of
re-reading pixels) but while a view is mounted the canvas switches to a managed
render loop. That is incompatible with EffectComposer/postprocessing and is
occluded by opaque DOM layered over the canvas — prefer useCameraStream for
panel tiles, and <CameraView> for transparent overlays.
Policy Image Tensors
For in-browser policy inference, capture straight into aFloat32Array — no
canvas, no PNG. usePolicyCameraTensors keeps one reusable session per camera
and re-aims it to the live MuJoCo pose each step:
captureCameraFrameTensor(); for lower-level
control, createCameraFrameCaptureSession() exposes captureTensor() and
capturePixels(), and pixelsToPolicyImageTensor() converts a raw RGBA buffer.