Venues: persistent room, motivated camera, ride; drop Pylon Grid

- Venue as one continuous place: persistent per-song layer, interpolated
  venueState, story jumps (one re-hang max + recap) with camera cuts
- Room camera shot plan (venueShots.js): per-section size/target, monotonic
  look sweep, traverse glide body, room-side alternation
- New Ride venue: generated vehicle + actor passengers, radio RTT screen,
  chase/stationary modes, ride archetype across generator/camera/staging
- Flora cost trim (5x(12+6+6) -> 4x(8+4+4) SDF evals, 204ms -> 140ms worst)
- Delete Pylon Grid shader (2.5s/frame SwiftShader); drop its metadata row
- tools/venue-check.js headless gate harness + venue-gallery explorer
This commit is contained in:
Dejvino
2026-09-17 19:35:26 +02:00
parent b1b6431eeb
commit 46fab512df
31 changed files with 3684 additions and 358 deletions
+7 -5
View File
@@ -69,11 +69,12 @@ function blockMean(byBlock) {
*
* @returns {{name, frames: Array, drift: number, direction: number, look}}
*/
export function renderSong(show, name, { duration, every }) {
export function renderSong(show, name, { duration, every, venueEnabled = null }) {
const { track } = song(name, { duration });
// Seeded off the song's name, so a strip is stable between rebuilds and two
// songs are not accidentally handed the same look.
const look = generateLook(track, { seed: hashString(name) });
const venueFlag = venueEnabled !== null ? !!venueEnabled : (typeof location !== 'undefined' && new URLSearchParams(location.search).get('venue') === '1');
const look = generateLook(track, { seed: hashString(name), venueEnabled: venueFlag });
show.useTrack(track, look);
const frames = [];
@@ -162,6 +163,7 @@ export function renderSong(show, name, { duration, every }) {
return {
name,
frames,
look,
drift: mean(dists),
direction: directionOf(gaps, dists),
// Agitation over the strip: worst 1 s floating window, max(flash/3,
@@ -205,7 +207,7 @@ function momentAt(story, index) {
* times for nothing.
*/
export async function buildFilmstrip({
duration = DEFAULT_DURATION, every = DEFAULT_EVERY, names = null,
duration = DEFAULT_DURATION, every = DEFAULT_EVERY, names = null, venueEnabled = null,
onSong = null, onSongStart = null,
} = {}) {
const list = names && names.length ? names : songNames();
@@ -223,9 +225,9 @@ export async function buildFilmstrip({
}
let row;
try {
row = renderSong(show, list[i], { duration, every });
row = renderSong(show, list[i], { duration, every, venueEnabled });
} catch (err) {
row = { name: list[i], frames: [], drift: 0, direction: 0, error: err.message };
row = { name: list[i], frames: [], shots: [], drift: 0, direction: 0, error: err.message };
}
rows.push(row);
if (onSong) onSong(i + 1, list.length, row);