# `.SPL` camera-path spline format Reverse-engineered from `DPL3/EXAMPLES/SPLINE.C`. A `.SPL` drives a camera (or a `DYNAMIC` object) along a smooth path. It is **plain text**: ``` N number of control points x y z ax ay az x N -- position + euler angles (degrees) ``` `ax ay az` are rotations about X, Y, Z (same convention as `STATIC`/`LIGHT` in the scene format). The path is a **closed loop** (the last point links back to the first). ## Interpolation Each of the 6 channels (x, y, z, and the three angles) is splined independently as a **cubic Hermite** curve with **Catmull-Rom tangents**: ``` tangent at knot i (position): vel = (pos[i+1] - pos[i-1]) / 2 tangent at knot i (angle): rot = wrap(ang[i+1] - ang[i]) / 2 ``` Per segment `i -> i+1`, with endpoint values `v0,v1` and tangents `d0,d1`, the cubic `v(t) = a t^3 + b t^2 + c t + d` (`t` in 0..1) is: ``` d = v0 c = d0 a = d1 + d0 - 2*v1 + 2*v0 b = v1 - v0 - d0 - a ``` (Angle segments additionally subtract 360 from a tangent > 360 before solving, as in the original `solve_rot_cubic`.) `walk_spline` advances `t` by a step, rolling over to the next/previous knot at the 0..1 boundaries — a constant-`dt` walk, so speed follows the control-point spacing (closely spaced points = slower). ## From a path sample to a camera At parameter `t` the sampled `(pos, ang)` becomes a camera basis. Build the DPL rotation `R = Rz(az) . Rx(ax) . Ry(ay)` (row-vector; see `SCN_FORMAT.md`), then: ``` forward = (0,0,-1) . R # the camera looks down its local -Z up = (0,1,0) . R eye = pos center = pos + forward ``` The `-Z` local-forward is confirmed by `CAMERA.SPL`: it starts at `(0,310,-500)` with `ay = 180`, which rotates local `-Z` to world `+Z` — i.e. the camera looks into the scene, which extends toward `+Z`. ## Validation `parser/spl.py` evaluates `CAMERA.SPL` (20 control points) into a smooth 240-frame loop, eye path `X[-260,230] Y[-15,842] Z[-759,58519]` — matching both the file's control points and the `RAPTOR.SCN` extent (`Z[-30000,75000]`). Rendered frames from the path (`viewer/flythru_*.png`) show a coherent first-person flight down the Raptor canal, banking as the euler angles interpolate. In the viewer, the fly- through animates the full loop; dragging drops back to manual orbit.