Continuity rule: discrete params hold per cue; add DESIGN.md + AGENTS.md

Actors and objects change only at camera cuts. int/bool/discrete
params skip drift, lookahead and reactivity; discrete slowAxis steps
on the section-held journey. Venues fade instead of toggling on
interpolated popMul; roadside density is arrangement-only.

DESIGN.md collects the project's design decisions; AGENTS.md points
agents at it and the build-visualizer loop.
This commit is contained in:
Dejvino
2026-09-20 16:42:44 +02:00
parent 6e70f95d4d
commit a99a7cbe49
15 changed files with 308 additions and 31 deletions
+12 -10
View File
@@ -727,18 +727,20 @@ export const chamber = {
const idx = g.userData.index || 0;
const isActor = g.userData.kind === 'actor';
// Actors are the subject: always dressed. Junk thins out in
// sparse setups via popMul, as before.
if (isActor) {
g.visible = opacity > 0.01;
} else {
const popMul = vState ? vState.popMul : 1;
const showIndex = idx / Math.max(1, instance.popCount);
g.visible = opacity > 0.01 && (showIndex < (0.35 + popMul * 0.75));
}
// sparse setups via popMul — as a SMOOTH opacity fade, never a
// visible toggle: the interpolated venueState crosses thresholds
// at arbitrary mid-section moments, and hard cuts there read as
// random flashes (same pattern as the ride's crew). Actors take
// the first indices so the fade never touches them.
const popMul = vState ? vState.popMul : 1;
const showIndex = idx / Math.max(1, instance.popCount);
const fade = isActor ? 1
: Math.max(0, Math.min(1, ((0.35 + popMul * 0.75) - showIndex) / 0.12));
g.visible = opacity > 0.01 && fade > 0.01;
g.traverse((mesh) => {
if (mesh.isMesh) {
mesh.material.opacity = opacity;
mesh.material.transparent = opacity < 0.999;
mesh.material.opacity = opacity * fade;
mesh.material.transparent = opacity * fade < 0.999;
// The room's population breathes with the story arc: dim in
// setup, bright at the climax. Pure f(venueState), no clock.
// Figures breathe brighter — they must read against their