feat(director): add authored camera directions and anchors

This commit is contained in:
Sameh Khamis committed 2026-09-15 16:53:26 -07:00
1 parent 0ea10468ea
commit 13c0b8d1bc
24 files changed
+1104 -167

No files matched your search

+8 -1
View File
@@ -1,5 +1,12 @@
# God's Eye View Current State
Director version-4 documents add named geographic anchors and optional explicit
camera moves with easing, duration and holds. Playback and seek share one
coordinate sampler; navigation/manual input revokes authored motion and pending
holds. Anchor heights and explicit endpoints require the WGS84 ellipsoid
reference. Legacy projects retain their ordinary flights, content and edits.
See [camera directions](DIRECTOR-CAMERA.md).
Realtime voice composes separate connection, response/tool, Radio handoff, input
and audio-meter, cost, viewport-context and diagnostic owners. The existing
controller exports and session/backend contracts remain available. Tool protocol,
@@ -27,7 +34,7 @@ holds; stale tick callbacks cannot publish into a replacement. Registered pack
rules own presentation overrides and Nepal map fallback without changing saved
shots or content. Scene-document validation and legacy migration now have separate
owners. Invalid imports preserve the current project; unreadable saved projects
are protected from fallback writes. Version 3 remains the export format, with
are protected from fallback writes. Version 4 is the export format, with
zero pitch, low camera heights, scope and detection edits preserved. See [the document contract](SCENE-DOCUMENT.md);
data packs and interactions remain planned in [Director](DIRECTOR.md).
+109
View File
@@ -0,0 +1,109 @@
# Director camera directions
Version 4 scene documents can name geographic anchors and describe an explicit
camera move followed by a hold. Existing camera-pose shots still use the ordinary
camera flight. Import, playback, Load, Replay and seek accept the new directions;
a visual anchor/path editor is a later authoring step.
```json
{
"version": 4,
"scenes": [{
"id": "austin",
"title": "Across Austin",
"anchors": [
{ "id": "west", "title": "West viewpoint", "lat": 30.2672,
"lon": -97.76, "alt": 6000, "altitudeReference": "ellipsoid" },
{ "id": "east", "title": "East viewpoint", "lat": 30.2672,
"lon": -97.73, "alt": 7000, "altitudeReference": "ellipsoid" }
],
"shots": [{
"id": "crossing",
"title": "Cross the city",
"durationSec": 4,
"holdSec": 2,
"camera": { "anchorId": "east", "heading": 10, "pitch": -45, "roll": 0 },
"move": {
"from": { "anchorId": "west", "heading": 350, "pitch": -45, "roll": 0 },
"easing": "cubic-in-out"
},
"visual": { "style": "normal" },
"layers": {}
}]
}]
}
```
## One owner for each authored value
An anchor is a scene-local geographic position, with a stable `id`, optional
`title`, latitude, longitude, height and explicit altitude reference. Each scene
accepts at most 1,024 anchors. IDs must be unique within that scene. References to
missing anchors fail validation before replacing a project.
The shot's `camera` is its destination. It can be an inline pose or an
`anchorId` plus orientation. The optional `move.from` uses the same pose/reference
shape. References cannot also carry inline coordinates. They do not form chains.
Heading, pitch and roll belong to each camera pose, so two shots can look in
different directions from the same geographic anchor. Omitted orientation uses
heading 0, pitch −35 and roll 0 degrees.
An explicit move requires `move.from`, `move.easing`, `durationSec` and `holdSec`.
Its duration is 0.2–86,400 seconds; the hold is 0–86,400 seconds. The destination
is not copied into another field. `linear` and `cubic-in-out` are the supported
easings. A shot without `move` retains the existing ordinary flight, even in a
version-4 file. Its destination may also reference an anchor.
Capture continues to create ordinary camera-pose shots. Update Shot stores the
current viewport as an inline destination, preserving an explicit move's start
and easing; it does not change a shared anchor and thereby move other shots.
Editing imported directions and anchors currently means editing the scene JSON.
## Coordinates and altitude
Latitude/longitude use WGS84 degrees. Orientation uses the application's Cesium
heading/pitch/roll convention in degrees: heading rotates from local north,
negative pitch looks down, and zero pitch is horizontal. Camera positions use
meters above the WGS84 ellipsoid, matching `Cartesian3.fromDegrees` and captured
camera poses. These heights are not mean-sea-level elevations or heights above
the visible surface.
Every anchor and every inline endpoint of an explicit move must say
`"altitudeReference": "ellipsoid"`. Ordinary legacy poses without that field
already use the same reference. Terrain-relative and mean-sea-level references
are rejected; no terrain request, default ground estimate or implicit conversion
is made. Authors must provide ellipsoidal heights with enough clearance for their
scene. The format does not promise collision avoidance or terrain following.
During an explicit move, latitude and altitude interpolate between endpoints.
Longitude takes the shortest signed arc across the dateline; heading and roll
also take their shortest signed arcs. An exact 180-degree tie takes the negative
arc. This is an authored coordinate interpolation, not a geodesic or a camera
flight with an automatically raised arc. Endpoints are exact, including zero
pitch. Curved paths and look-at targets are later extensions.
## Time, seeking and cancellation
Load and Replay of an explicit move start at its authored `from` pose, regardless
of the current viewport. Play uses that same start. Both live playback and seek
use `sampleCameraMove`; a seek into the hold uses the exact destination. Backward
seeks do not depend on a prior camera position. Existing scene-pack media/reveal
rules can extend holds as before.
Each active explicit move owns one animation-frame callback. Stop, replacement,
import, teardown, a navigation handoff or manual pointer/wheel input revokes that
callback and settles the move. Navigation also cancels a run during an authored
hold, so the next shot cannot retake the camera. Camera claims still respect
Cockpit's refusal. Already queued callbacks cannot move a replacement scene.
The timing diagnostic includes the active authored camera animation.
The renderer-independent `gods-eye-view/director` export provides
`resolveCameraPose(scene, camera)`, `resolveCameraMove(scene, shot)` and
`sampleCameraMove(move, progress)`. These expect validated/normalized data.
Rendering and frame ownership live in `src/scenes/cameraMotion.js`; the existing
scene controller supplies camera application and lifecycle cancellation.
Version-1/2/3 projects migrate to version 4 without converting their ordinary
shots into explicit moves. IDs, positions, durations, visual settings, packs and
source attribution survive. The bloom scale remains independent of the document
version; version-3 bloom is never interpreted as the older inverted scale.
+7 -6
View File
@@ -67,16 +67,17 @@ and river coordinates are bundled. See the
existing recipes and content. Tests cover direct load, forward/backward seek,
replay, bounded media waits and cancellation at pending transitions.
2. **Versioned scene document — implemented for existing camera-pose shots.**
[Version 3](SCENE-DOCUMENT.md) remains the write format. Bounded validation
[The scene document](SCENE-DOCUMENT.md) preserves version-1/2/3 imports. Bounded validation
rejects malformed files before replacing current state; legacy migration
preserves IDs, pack bindings and visual edits. Unreadable saved files are
protected from fallback writes. Camera anchors, pack manifests and actions
receive stable IDs with their respective later format extensions.
3. **Camera directions.** Define named geographic anchors and explicit
move/hold segments: start and destination, duration, easing, heading, pitch,
roll and stop duration. State coordinate units, altitude reference and
terrain-relative behavior. Support the current camera-pose shots first;
paths, look-at targets and pauses follow with deterministic seek behavior.
3. **Camera directions — implemented for pose-to-pose moves.**
[Version 4](DIRECTOR-CAMERA.md) adds scene-local geographic anchors, explicit
start/destination poses, easing, duration and holds. Playback and seek share
the same sampler. Ellipsoidal heights are explicit; terrain-relative input
is rejected. Existing shots retain ordinary flights. Curved paths, look-at
targets and visual authoring are later extensions.
4. **Data packs and placement.** Define a pack manifest with format/version,
source, attribution/license and optional integrity/size metadata. Distinguish
where bytes live (relative files, a URL, or an eventual bundle) from where
+14 -15
View File
@@ -1,13 +1,13 @@
# Scene document version 3
# Scene document format
Scenes exports a UTF-8 JSON project. Version 3 remains the write format; existing
version-3 exports need no conversion. Versions 1, 2 and unversioned legacy files
are migrated on import. Unknown versions or unsupported fields are rejected with
Scenes exports a UTF-8 JSON project. Version 4 adds [camera directions](DIRECTOR-CAMERA.md)
and is the write format. Versions 1, 2, 3 and unversioned legacy files migrate on
import without converting their existing shots into authored moves. Unknown versions or unsupported fields are rejected with
a field path before the current project, selection or saved bytes change.
```json
{
"version": 3,
"version": 4,
"scenes": [{
"id": "my-scene",
"title": "My scene",
@@ -30,21 +30,21 @@ a field path before the current project, selection or saved bytes change.
The root requires `scenes` (an array, which may be empty). Optional root fields
are `version`, `createdAt`, `updatedAt` and `installedBuiltInSceneIds` (string IDs).
Each scene requires a `shots` array; optional fields are `id`, `title`,
`releaseLayerIds` and `appliedShotPacks`. A pack marker has `id`, optional numeric
`releaseLayerIds`, `appliedShotPacks` and version-4 `anchors`. A pack marker has `id`, optional numeric
`version` and `shotBindings` (original shot title to saved shot ID). These markers
retain the editor's existing pack-update and rename behavior.
Shots accept `id`, `title`, `durationSec`, `holdSec`, `camera`, `visual`, `layers`,
`sourcePackId` and `sourcePackVersion`. Scene IDs are unique within the project;
`sourcePackId`, `sourcePackVersion` and version-4 `move`. Scene IDs are unique within the project;
shot IDs are unique within their scene. Existing IDs and pack bindings survive
migration. Missing IDs are generated once and persisted by the next save/export.
Missing titles and optional camera/visual fields receive the editor's defaults.
Empty scenes and intentionally empty projects remain empty.
Camera latitude/longitude and heading/pitch/roll use degrees. Altitude uses the
existing camera-pose height in meters. Import preserves finite heights below
100 meters and zero pitch, which previously fell through to defaults. Explicit
altitude-reference and terrain-relative directions are a subsequent format step.
Camera latitude/longitude and heading/pitch/roll use degrees. Altitude uses
meters above the WGS84 ellipsoid. Import preserves finite heights below
100 meters and zero pitch, which previously fell through to defaults. Anchors and explicit moves require the `ellipsoid` altitude reference;
terrain-relative inputs are rejected. See the camera contract for exact semantics.
Flight durations retain the editor's minimum of 0.2 seconds and its 4-second
fallback for zero; holds may be zero.
@@ -95,8 +95,7 @@ can preserve temporary edits. Storage writes use the same validation before repl
edits and storage write failures surface an unsaved toast.
Only authored project fields belong in this file. Runtime clocks, camera flights,
loading progress and run diagnostics remain separate. Camera anchors, asset-pack
manifests and declarative interactions are planned extensions, not accepted fields
in version 3. They will receive stable IDs and their own validated migration when
introduced. No scene assets, source links, licenses or contributor attribution
loading progress and run diagnostics remain separate. Version 4 supports scene-local camera anchors and authored moves. Asset-pack
manifests and declarative interactions remain planned extensions. They will
receive stable IDs and their own validated migration when introduced. No scene assets, source links, licenses or contributor attribution
change with this document boundary.