feat: cinematic outro that mirrors the intro crane
On arrival the camera cranes back toward the sun on a long lens, letterbox bars close in on every tier and a closing credit of real identity facts fades into the upper bar. Leaving the destination reverses it.
This commit is contained in:
@@ -184,6 +184,9 @@ export async function createProceduralSceneGeneration(
|
||||
let introProgress: number | null = null;
|
||||
let introFrames = 0;
|
||||
let introSlowFrames = 0;
|
||||
// The outro mirrors the intro: on arrival the camera cranes back up toward
|
||||
// the sun on a long lens. Leaving the destination reverses it, faster.
|
||||
let outroProgress = 0;
|
||||
let gantryState = '';
|
||||
|
||||
const resize = (): void => {
|
||||
@@ -515,9 +518,18 @@ export async function createProceduralSceneGeneration(
|
||||
if (introSlowFrames >= 3) introProgress = 1;
|
||||
introProgress = Math.min(1, introProgress + deltaSeconds / INTRO_SECONDS);
|
||||
}
|
||||
outroProgress = THREE.MathUtils.clamp(
|
||||
outroProgress
|
||||
+ (snapshot.arrived ? deltaSeconds / OUTRO_SECONDS : -deltaSeconds / OUTRO_RETURN_SECONDS),
|
||||
0,
|
||||
1,
|
||||
);
|
||||
// Part of the way back, not all: the end shot holds the sun, the
|
||||
// skyline and the road running into them, like a film's last frame.
|
||||
const outro = easeInOutCubic(outroProgress) * OUTRO_REACH;
|
||||
const crane = easeInOutCubic(
|
||||
THREE.MathUtils.clamp((introProgress - 0.06) / 0.94, 0, 1),
|
||||
);
|
||||
) * (1 - outro);
|
||||
const craneShift = cameraState.shift * crane;
|
||||
camera.setViewOffset(
|
||||
width,
|
||||
@@ -597,6 +609,9 @@ export async function createProceduralSceneGeneration(
|
||||
}
|
||||
|
||||
const INTRO_SECONDS = 4.2;
|
||||
const OUTRO_SECONDS = 5.5;
|
||||
const OUTRO_RETURN_SECONDS = 1.6;
|
||||
const OUTRO_REACH = 0.62;
|
||||
|
||||
function easeInOutCubic(t: number): number {
|
||||
return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
||||
|
||||
Reference in New Issue
Block a user