Setting the file. One moment.
Skill 10 · Frost Sequence Camera Orbit
Subchapter 10.24
Also bundled
Frost Sequence Camera Orbitsource/src/core/motion.ts
TypeScript81 lines2 KB
import type { Schedule, Pose } from "../frost";
export const SETTLE = 2.8;
export const ATTACK = 0.65; // anticipation before each break
const clamp01 = (x: number) => Math.max(0, Math.min(1, x));
/** C2 turn envelopes: continuous velocity/acceleration over an ongoing drift. */
export function makePoseAt(S: Schedule, P: Pose) {
const flowEase = (u: number) => {
u = clamp01(u);
return u * u * u * (u * (u * 6 - 15) + 10);
};
/** Quintic rise and fall meet with zero velocity and acceleration at the crest. */
const bump = (u: number, a: number) =>
u <= a ? flowEase(u / Math.max(a, 1e-6)) : 1 - flowEase((u - a) / Math.max(1 - a, 1e-6));
type Turn = {
t0: number;
tBreakEnd: number;
t1: number;
yaw: number;
pitch: number;
z: number;
keep: boolean;
};
const turns: Turn[] = [
{
t0: S.logoBreak - ATTACK,
tBreakEnd: S.form1,
t1: S.form1 + SETTLE,
yaw: P.turnYaw,
pitch: P.turnPitch,
z: P.approach,
keep: false,
},
{
t0: S.break1 - ATTACK,
tBreakEnd: S.form2,
t1: S.form2 + SETTLE,
yaw: P.turnYaw2,
pitch: P.turnPitch2,
z: -P.retreat,
keep: false,
},
{
t0: S.break2 - ATTACK,
tBreakEnd: S.fadeOut + 1.5,
t1: S.fadeOut + 1.5,
yaw: P.finalYaw,
pitch: P.finalPitch,
z: P.approach + P.zoomIn,
keep: true,
},
];
/** the keyed part of the path (without drift / idle), in degrees and units */
function keyPoseAt(t: number) {
let yaw = 0,
pitch = 0,
z = 0;
for (const k of turns) {
const u = (t - k.t0) / Math.max(k.t1 - k.t0, 1e-6);
if (u <= 0) continue;
yaw += k.yaw * flowEase(u);
const a = (k.tBreakEnd - k.t0) / Math.max(k.t1 - k.t0, 1e-6);
const b = k.keep ? flowEase(u) : bump(u, a);
pitch += k.pitch * b;
z += k.z * b;
}
return { yaw, pitch, z };
}
const driftYawAt = (t: number) => P.driftYaw * t;
const idleYawAt = (t: number) => P.idleYaw * Math.sin((2 * Math.PI * t) / 9);
return function poseAt(t: number) {
const k = keyPoseAt(t);
const sway = P.driftSway * Math.sin((2 * Math.PI * t) / 11);
return {
yaw: k.yaw + driftYawAt(t) + idleYawAt(t),
pitch: k.pitch + sway,
z: k.z + 0.0875 * P.driftSway * Math.sin((2 * Math.PI * t) / 11),
};
};
}