Skip to main content
Documentation

Camera and modes

Switch view modes, navigate observer points, move the camera, and restore a saved scene view.

On this page

Build viewing controls after the scene has loaded.

Run the example

Open SDK examples in the running starter. Try the mode control, next viewpoint, camera turn, and saved-view controls. Check the scene itself after each action.

Switch the mode

Use the public changeMode operation and await its result. The supported mode values used here are Panorama, Floorplan, and Topview. Listen for the completed change before updating a control's selected state.

import type { Five, Mode } from "@realsee/five";

export type SceneView = Extract<Mode, "Panorama" | "Floorplan" | "Topview">;

/** Await this from a button handler; show a recoverable error on rejection. */
export async function changeView(five: Five, view: SceneView): Promise<void> {
  await five.changeMode(view, undefined, { duration: 500 });
}

/** Subscribe to the completed mode change, and call the returned cleanup. */
export function watchView(
  five: Five,
  onChange: (view: Mode) => void
): () => void {
  onChange(five.currentMode);
  return five.on("mode.change", (event) => onChange(event.mode));
}

A Work may not contain the model or assets a mode needs. Keep the current scene available and show the rejected operation rather than claiming that every scene supports every mode.

Choose from the loaded Work's observers where active || loadable is true, matching Five SDK 6.9.2's runtime navigation checks. These are alternatives: the published Public Demo has active observers whose loadable flag is false. Requiring both flags would incorrectly remove every destination. A panorama index on its own is insufficient when a viewer contains more than one Work; keep workCode with panoIndex.

import type { Five, Pano, Pose } from "@realsee/five";

/** Five 6.9.2 accepts active OR explicitly loadable observers, not both flags. */
export function listDestinations(five: Five): Pano[] {
  return five.observers
    .filter((observer) => observer.active || observer.loadable)
    .map((observer) => ({
      workCode: observer.work.workCode,
      panoIndex: observer.panoIndex,
    }));
}

export async function goToDestination(five: Five, pano: Pano): Promise<void> {
  await five.moveToPano(pano, { effect: "fade", duration: 500 });
}

/** Angles use radians. This rotates/zooms without changing the panorama. */
export async function lookAt(
  five: Five,
  pose: Pick<Pose, "longitude" | "latitude" | "fov">
): Promise<void> {
  await five.updateCamera(pose, 500);
}

Camera angles use radians. updateCamera changes the viewing pose; moveToPano changes the panorama. Keep these as separate UI actions so the user knows what will happen.

Save and restore a view

Copy the current state into a serializable snapshot. A live Three.js vector must not be stored by reference. Restore a trusted snapshot only after its matching Work is loaded.

import type { Five, State } from "@realsee/five";
import { Vector3 } from "three";

export type SavedView = Omit<State, "offset"> & {
  offset: [number, number, number];
};

/** The returned value is JSON serializable and does not retain live vectors. */
export function saveView(five: Five): SavedView {
  const state = five.getCurrentState();
  return {
    ...state,
    offset: [state.offset.x, state.offset.y, state.offset.z],
  };
}

/** Restore only a trusted snapshot for the same loaded Work. */
export function restoreView(five: Five, view: SavedView): void {
  if (view.workCode !== five.work.workCode)
    throw new Error("Load the snapshot's Work before restoring its view.");
  five.setState({ ...view, offset: new Vector3(...view.offset) }, true);
}

The snapshot identifies a view, not permission to fetch that Work. A deployed application must authorize the resource independently.

Check the result

Switch Panorama → Floorplan → Panorama. Save a view, move elsewhere, then restore it. The restored position and viewing direction should match the saved state. Report a mode rejection separately from a successful camera movement.

Continue with Events and coordinates.