Skip to content

spike(camera): video-recording showcase drivers (cosmic-flows + named cosmic web)#354

Draft
rulkens wants to merge 16 commits into
mainfrom
worktree-fly-to-edge-spike
Draft

spike(camera): video-recording showcase drivers (cosmic-flows + named cosmic web)#354
rulkens wants to merge 16 commits into
mainfrom
worktree-fly-to-edge-spike

Conversation

@rulkens

@rulkens rulkens commented Jun 19, 2026

Copy link
Copy Markdown
Owner

What

Throwaway camera spike (worktree-fly-to-edge-spike) for recording skymap hero clips. Opened as a draft — it carries spike-only camera drivers and is not meant to land as-is. Branch is caught up with main.

Recording drivers (URL-gated in startLoop.ts)

  • ?flowshow — choreographed "cosmic flows" hero clip (24 s; ?flowshow=<mpc> sets the pull-back distance).
  • ?webshownamed cosmic web clip (this round): slow-orbit the local structure neighbourhood while cluster/SC/void rings + labels sweep through, ease the camera out to Virgo, then fire structure focus (the double-click gesture) to isolate Virgo's members — non-members fade to ~8% via the existing GPU cone-search. ?webshow=<mpc> overrides the opening orbit distance.
  • ?flyout=<sec>, ?floworbit — earlier camera drivers.

For both showcase drivers: h to home, ensure the scene is framed, Tab to hide UI, g to start (2 s static pre-roll to hit record). Reload between takes.

Also in this branch

🤖 Generated with Claude Code

rulkens and others added 6 commits June 19, 2026 00:17
Three priority-80 CameraDriver spikes for recording promo clips of the
renderer, gated behind URL flags and toggled with `g`:

  - ?flyout     log-dolly pull-back MW -> horizon shell (~29500 Mpc)
  - ?floworbit  seamless orbit + gentle pitch-bob
  - ?flowshow   choreographed multi-beat "cosmic flows" hero clip that
                owns both the camera and the scene/layer state

These also scout the parked guided-tour feature. Findings written up in
docs/research/2026-06-19-camera-animation-spike-findings.md (driver owns
choreography, fade-through-FadeRegistry to dodge the settings-store
staleness bug, log-space dolly, storyboard grammar). Label-declutter
flicker under camera motion captured in BACKLOG.

THROWAWAY: the driver code + the settingsStore threading through
BootstrapDeps/engine.ts/startLoop and the ?nodeclutter gate are not meant
for main; this branch is kept only as a reference capture. The doc + the
BACKLOG note are the parts worth carrying forward.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#345)

The zustand settings store was migrated to Redux Toolkit, injected at the
app root and reachable as `cb.store` (AppStore). That deletes the spike's
whole BootstrapDeps.settingsStore thread:

  - drop the `settingsStore?` field + its (now-moved) import from BootstrapDeps
  - drop the `settingsStore` entry from engine.ts's bootstrapDeps literal
  - startLoop reaches the store via `deps.cb.store` instead
  - retype the flowshow driver's `store` param zustand SettingsStore -> AppStore
  - guard `window` in startLoop's optional `?flyout`/`?floworbit`/`?flowshow`
    value reads so the node-env phase unit tests stop throwing

The handle setters (setFlow/setVolumes/…) still take `(state, store, patch)`,
so the driver's scene-setup calls are unchanged. Typecheck + tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR #352 dissolved the engine `handles/setX` setters into reconcile sagas.
The flowShowcaseDriver still imported the deleted `setFlow` /
`setVolumesEnabled` / `setFilamentsEnabled` / `setGalaxyCatalogLabelEnabled`
handles, which broke the dev bundle after merging main. Dispatch the
equivalent settingsSlice actions instead — the reconcile sagas now fire the
side effects (requestRender, syncVisibilityFades, flow reseed) the old
setters used to.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 19, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
skymap 081b6ef Commit Preview URL

Branch Preview URL
Jun 20 2026, 10:43 PM

A second throwaway recording driver for the "named cosmic web" social clip:
slow-orbit the local structure neighbourhood while cluster/SC/void rings +
labels sweep through, ease the camera out to Virgo, then fire structure focus
(the double-click gesture) to isolate Virgo's members — non-members fade to
~8% via the existing GPU cone-search. Gated on ?webshow (=<panMpc> overrides
the opening orbit distance); press g in-app to run a take.

Isolation is triggered through the current selection seam
(state.subsystems.selection.setFocused); a one-line retarget when PR #350
folds selection into the Intent store.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rulkens rulkens changed the title spike(camera): cosmic-flows showcase driver (video recording) spike(camera): video-recording showcase drivers (cosmic-flows + named cosmic web) Jun 19, 2026
rulkens and others added 9 commits June 19, 2026 13:53
The structure store keys anchors as `${category}-${seed.id}`, so Virgo is
`cluster-virgo-m87`, not `virgo-m87`. The wrong id resolved to null, which
(both the target-lerp and the dolly being null-guarded) froze the camera at
the pan distance — no approach, no isolate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The findIndex-by-id + buildGalaxyInfo lookup that turns a famous id into a
resolved GalaxyInfo was hand-rolled inside selectFamous; the recording drivers
want the same resolve. Pull it into one helper (null guards — cloud not loaded,
unknown id — in a single place) and route selectFamous through it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
After isolating Virgo's members, the clip now log-dollies from the cluster
framing down to M87's focus distance so its curated thumbnail resolves — the
"named web → one real galaxy" payoff. Virgo stays focused (a galaxy focus
would cancel the isolation), so M87, a member, holds bright while the rest of
the sky stays dimmed. Resolves M87 via the shared resolveFamousGalaxy helper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Focus isolates a structure's members (non-members dim to ~8%) but a galaxy
focus dims nothing. Captured as a surfaced issue with the essential-vs-
accidental question to resolve before acting, noted while the webshow spike
worked around it (M87 dive keeps Virgo focused).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…spike

# Conflicts:
#	src/services/engine/engine.ts
Three tuning changes to the ?webshow named-cosmic-web driver:

- Fire the Virgo focus the instant the approach settles (CLICK_DELAY_SEC
  0.8 -> 0), so the isolation lands on the same beat as the camera
  arriving rather than after a pause.
- Collapse the two cluster framings into one. The approach landed at
  ring framing (1.8x) but the dwell then dollied past it to close
  framing (0.9x), so the click's resting spot never matched where the
  approach arrived. The dwell now HOLDS the ring framing the approach
  landed on; the M87 dive starts from there.
- Lift the isolation at the end of a take: after a 4 s wait orbiting
  M87, dispatch updateSelectionFocus(null) so the dimmed background
  fades back in, then release. A full take now self-cleans, so no
  reload is needed between takes (an aborted take still latches).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…spike

Brings in the camera-pose-as-derived-state refactor (#357) + the
focus-tween fold into watchFocusTween (#358). The CameraDriver contract
changed from a mutating apply(cam, nowMs) to a pure pose(s, cam,
elapsedMs) that RETURNS a CameraPose; assembleOrbitCamera derives
position from it.

Migrated the four throwaway spike drivers (webshow / flowshow / flyout /
floworbit) to the new contract:

- apply(cam) mutation -> pose() returning a fresh CameraPose; no more
  updatePosition (the resolver derives position via assembleOrbitCamera).
- Self-clock via performance.now(): the driver-table elapsed clock
  (elapsedForWinner) only serves the 'tween'/'autoRotate' ids, so any
  other driver id receives elapsedMs === 0.
- Self-sustain the loop: shouldKeepTicking reads camera liveness off the
  store (drag/tween/autoRotate), so a spike driver gating on local phase
  is invisible to it; each driver now pokes requestRender() per frame or
  the take freezes after one tick.
- priority 80 -> 90: orbitDrag now occupies 80, so the takes move above
  the store movers to keep owning the camera.
- Drop the fovYRad set (CameraPose carries no FOV); framing reads the
  live projection FOV off the forwarded cam.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tRender

After the pose-as-derived-state merge, each throwaway spike driver had to
poke requestRender() every frame to stay alive, because shouldKeepTicking
derives camera liveness from STORE flags (selectCameraActive) and a spike
driver moves the camera without touching the store — so it was invisible
to the keep-tick gate.

Move that responsibility to runFrame, which already resolves `activeId`:
keep ticking whenever a non-`resting` driver owns the frame. For the
built-in drivers this coincides with selectCameraActive (behaviour
preserved); it ALSO covers any driver that animates the camera outside the
store — today's recording spikes, the tour driver later. The drivers go
back to being pure pose producers; the per-frame requestRender is gone
(the `g`-keypress wake stays — that's a real input channel).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant