← All Baltor Engineering Posts · Post 05 of 08 · 2026-10-18 · Creative Production & Motion · 7 min read · Raw Markdown (.md) · Open Live Studio ↗

60 FPS Motion Graphics: Why Spring Physics and DFT Epicycles Beat CSS Keyframes

Linear CSS keyframes snap unnaturally when interrupted and cannot synchronize complex vector contours with audio phases. Baltor uses analytical second-order spring solvers and Discrete Fourier Transform epicycles.


PHASE-CONTINUOUS MOTION ENGINE: SECOND-ORDER SPRINGS + N-CIRCLE DFT EPICYCLES SECOND-ORDER DAMPED HARMONIC OSCILLATOR x''(t) + 2*zeta*omega_0*x'(t) + omega_0^2*(x - x_target) = 0 Preserves C1 velocity continuity across mid-flight target changes and camera beat transitions Critically Damped (zeta = 1.0) | Underdamped (zeta = 0.65) DISCRETE FOURIER TRANSFORM (DFT) EPICYCLE CHAIN X_k = (1/N) * sum_{n=0}^{N-1} z_n * exp(-i*2*pi*k*n/N) Sorts rotors by amplitude |X_k| and locks WebAudio harmonic partials to exact geometric rotor phases 60 FPS deterministic scrub at any timestamp t

When an unassisted model generates a motion-graphics sequence or an animated startup pitch, it defaults to hardcoded CSS @keyframes or linear setTimeout chains. As soon as a user scrubs the timeline, resizes the viewport, or triggers an interactive state change mid-transition, CSS keyframes snap discontinuously in velocity (C0 only, violating C1 momentum conservation). By replacing piecewise keyframe timers with analytical second-order spring solvers and Discrete Fourier Transform (DFT) epicycle chains on agentstudios.si and compare.baltor.ai, Baltor motion components maintain smooth 60 FPS velocity continuity and exact timestamp scrubbability (renderAtTime(t)).

Analytical second-order spring integration

A physical spring parameterized by natural angular frequency omega0 = sqrt(stiffness / mass) and damping ratio zeta = damping / (2 * sqrt(stiffness * mass)) satisfies the differential equation:

x''(t) + 2 * zeta * omega0 * x'(t) + omega0^2 * (x(t) - target) = 0

Unlike naive explicit Euler integration (v += a * dt; x += v * dt), which explodes when stiffness > 300 and a browser frame lags to 50 ms, Baltor's motion primitive (motion.spring.analytical_2d.v1) evaluates the exact closed-form exponential solution for underdamped (zeta < 1), critically damped (zeta == 1), and overdamped (zeta > 1) regimes:

// Unconditionally Stable Analytical Damped Spring Step
export function stepAnalyticalSpring(x, v, target, omega0, zeta, dt) {
  const x0 = x - target;
  if (zeta < 1.0 - 1e-5) {
    const omegaD = omega0 * Math.sqrt(1.0 - zeta * zeta);
    const env = Math.exp(-zeta * omega0 * dt);
    const cosTerm = Math.cos(omegaD * dt);
    const sinTerm = Math.sin(omegaD * dt);
    const c1 = x0;
    const c2 = (v + zeta * omega0 * x0) / omegaD;
    const nextX = target + env * (c1 * cosTerm + c2 * sinTerm);
    const nextV = env * (
      (c2 * omegaD - c1 * zeta * omega0) * cosTerm -
      (c1 * omegaD + c2 * zeta * omega0) * sinTerm
    );
    return { x: nextX, v: nextV };
  }
  const env = Math.exp(-omega0 * dt);
  const c1 = x0;
  const c2 = v + omega0 * x0;
  return {
    x: target + env * (c1 + c2 * dt),
    v: env * (c2 - omega0 * (c1 + c2 * dt))
  };
}

Complex DFT epicycles for closed-contour drawing

To animate complex vector emblems, technical diagrams, and cursive glyphs while synthesizing phase-locked audio, Baltor treats any closed 2D path as a sequence of complex samples z[n] = x[n] + i * y[n] (n = 0 ... N-1) and computes its exact Discrete Fourier Transform:

X[k] = (1 / N) * sum_{n=0}^{N-1} z[n] * exp(-i * 2 * pi * k * n / N)

Sorting the resulting Fourier modes by descending radius |X[k]| allows the renderer to reconstruct the contour using M <= 64 rotating epicycle vectors while driving a WebAudio additive synthesizer from the same harmonic amplitudes and phases.


Navigation Post Title Direct Links
Previous Post Building Playable Godot 4 and WebGL Games That Survive Revision
Next Post Procedural 3D Product Commercials in the Browser: Anisotropic Metals, Rim Lights, and Camera Beats
Blog Index & Feeds Return to Baltor Engineering Blog Index (8 Posts)