Camera Tour Planner

Builds camera waypoint sequences for building walkthroughs. The planner extracts spaces and portals, samples viewpoints, orders them, then smooths the result into a CameraTour. Inspired by Liu, Xu & Sun (2012), "Automatic camera path planning for IFC building models" (Automation in Construction).

Pipeline:

  1. Extract spaces + door portals from the source (default: IFC semantic walk over a paired DataModel).
  2. Sample candidate viewpoints inside each space, scored by visibility coverage.
  3. Plan the tour order. The default starts with a greedy nearest-neighbour pass and refines with 2-opt. Pass planTourGreedy to skip refinement.
  4. Smooth the stops into a waypoint list ready for CameraPath + CameraPathAnimation playback.

The planner returns data only. playCameraTour applies a tour to a View's Camera, so tours can be planned server-side and loaded with a model.

Source files are bucketed into graph/ (the space + viewpoint graph types), plan/ (planning entry point + result/options types), build/ (the smoothing leg), and play/ (playback runtime). The strategy subdirs (extractors/, samplers/, planners/) and internal/ are part of the same module. The public symbols are re-exported from this barrel.

Three steps: plan, play, then drive the playback handle from UI.

import {
planCameraTour,
playCameraTour,
extractSpacesFromGeometry,
} from "@xeokit/sdk/presentations/cameraTour";

Planning is data-only. The IFC space extractor is the default; pass extractor: extractSpacesFromGeometry for non-IFC sources.

const planResult = await planCameraTour({
sceneModel: scene.models["building"],
dataModel: data.models["building"],
options: {
samplesPerSpace: 8,
dwellSeconds: 2.5,
transitionSeconds: 1.5,
},
});

if (!planResult.ok) throw new Error(planResult.error);
const tour = planResult.value;

Drives the View's Camera through the planned waypoints and returns a CameraTourPlayback handle for pause, seek, and disposal.

const playResult = playCameraTour(view, tour, {
rate: 1.0,
loop: false,
onWaypoint: (i, w) => console.log(`Now in ${w.spaceLabel}`),
});

if (!playResult.ok) throw new Error(playResult.error);
const playback = playResult.value;

Wire the playback handle to the host UI.

pauseBtn.onclick   = () => playback.pause();
playBtn.onclick = () => playback.play();
seekSlider.oninput = () => {
playback.progress = +seekSlider.value / 100;
};

For glTF, OBJ, dotbim, or other sources without IfcSpace metadata, use the geometry-only extractor.

const planResult = await planCameraTour({
sceneModel: scene.models["mesh-only"],
extractor: extractSpacesFromGeometry,
});

Interfaces

CameraTour
CameraTourPlanOptions
CameraTourPlanParams
CameraTourPlayback
CameraTourWaypoint
PlayCameraTourOptions
SpaceExtractor
SpaceExtractorInput
SpaceGraph
SpaceGraphEdge
SpaceGraphNode
TourPlanner
TourPlannerInput
TourPlanResult
TourStop
ViewpointGraph
ViewpointGraphNode
ViewpointSampler
ViewpointSamplerInput

Variables

extractSpacesFromGeometry
extractSpacesFromIfc
planTourGreedy
planTourTwoOpt
sampleVisibilityGrid

Functions

planCameraTour
playCameraTour