SCENEGOD/scenegod/web/grammar.js
type-two 20af1b20c2 [m5+m6] DIRECTOR MODE + FLOW VIDEO PLATES — all lanes + sync6 seam fixes
Lane A: grammar.js (shot/angle/focal/light/mark data), presets.js (bbox shot
solver, light/mark appliers, DIRECT bar UI, NL box), stage video plates
(VideoTexture plane/corner/dome, screen kind, syncVideos), dock video cards.
Lane B: scenegod:direct → grouped-undo keys/cuts, 🗣 lip-sync from audio via
/rhubarb, Cmd+wheel zoom / wheel scroll, audio trim, video clock-follow via
nullable entityVideo seam. Lane C: POST /director (LLM proxy, server-side op
validation vs vocab+scene, mock-tested), render.js awaits stage.syncVideos.
Sync6 (orchestrator): VIDEO_EXTS in server tree/media types (video primary,
img poster as thumb), stage.entityVideo accessor, syncVideos forces
videoTex.needsUpdate (rVFC never fires in hidden tabs → black plates).

Verified: 9 server groups + timeline + presets suites green; browser SYNC:
one-click MCU framing lands camera+fov keys+cut (single undo), golden_hour
relight keys, plate scrub-follow frame-exact, finalRender mp4 shows the Flow
golden-hour street plate behind an animated character.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 17:51:28 +10:00

58 lines
3.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// grammar.js — classic cinema vocabulary as PURE DATA (Lane A owns; every lane reads).
// No imports, no DOM, no three — safe under plain node. Presets/LLM ops both resolve here,
// so the button path and the /director path can never drift apart.
// Shot sizes: vertical span the framing should cover, as a fraction of subject height,
// @ where the frame centers on the body (fraction of subject height from the feet).
export const SHOTS = {
ECU: { span: 0.12, center: 0.93, label: 'extreme close-up' },
CU: { span: 0.25, center: 0.87, label: 'close-up' },
MCU: { span: 0.45, center: 0.75, label: 'medium close-up' },
MS: { span: 0.65, center: 0.65, label: 'medium shot' },
MWS: { span: 0.85, center: 0.55, label: 'medium wide' },
WS: { span: 1.2, center: 0.5, label: 'wide shot' },
EWS: { span: 2.5, center: 0.5, label: 'extreme wide' },
};
// Camera attitude relative to the aim point. elev = degrees above (+) / below () the
// aim; roll = dutch tilt in degrees; ots = over-the-shoulder of the OTHER subject.
export const ANGLES = {
eye: { elev: 0, roll: 0 },
low: { elev: -18, roll: 0 },
high: { elev: 22, roll: 0 },
dutch: { elev: 0, roll: 8 },
ots_L: { elev: 0, roll: 0, ots: 'L' },
ots_R: { elev: 0, roll: 0, ots: 'R' },
};
// Full-frame focal lengths (mm). Vertical fov = 2·atan(12/f) — 24mm-tall sensor.
export const FOCALS = [18, 24, 35, 50, 85];
// Lighting looks: key ("sun") color/intensity + boom direction (degrees), hemisphere
// ambient, and a background clear color. Values are what applyLight writes verbatim.
export const LIGHTS = {
day: { sun: { color: '#fff6e4', intensity: 3.0, elev: 55, azim: 35 },
ambient: { color: '#dfe9ff', intensity: 1.15 }, bg: '#8fb0d6' },
golden_hour: { sun: { color: '#ffb469', intensity: 2.6, elev: 9, azim: -55 },
ambient: { color: '#ffd9b0', intensity: 0.55 }, bg: '#d98a52' },
night: { sun: { color: '#7e93d6', intensity: 0.6, elev: 40, azim: 150 },
ambient: { color: '#31405e', intensity: 0.4 }, bg: '#0a0e1a' },
noir: { sun: { color: '#ffffff', intensity: 3.4, elev: 52, azim: 75 },
ambient: { color: '#1c1c24', intensity: 0.15 }, bg: '#08080a' },
horror: { sun: { color: '#b9d6a4', intensity: 1.7, elev: -30, azim: 10 }, // underlight
ambient: { color: '#25302b', intensity: 0.25 }, bg: '#05070a' },
neon: { sun: { color: '#ff4fd8', intensity: 1.9, elev: 25, azim: 120 },
ambient: { color: '#2de2e6', intensity: 0.9 }, bg: '#150420' },
overcast: { sun: { color: '#dfe4ea', intensity: 1.2, elev: 70, azim: 0 },
ambient: { color: '#c7cdd6', intensity: 1.4 }, bg: '#9aa3ad' },
};
// Blocking marks, stage-relative. pos marks move (keep current y); face marks rotate.
export const MARKS = {
center: { pos: [0, 0, 0] },
two_shot_L: { pos: [-0.7, 0, 0] },
two_shot_R: { pos: [0.7, 0, 0] },
face_camera: { face: 'camera' },
face_other: { face: 'other' },
};