Bring the graphics-dev collaborator's dpl3-revive into the repo as first-class
project code (they've handed it off; it's ours now). This is the proven
Division renderer that our in-process rt_draw has been trying to be.
What's here:
- parser/ B2Z/V2Z/SVT/SCN/SPL/BGF/BMF/BSL decoders (pure Python).
- spec/ reverse-engineered format + the definitive VelociRender wire
protocol (from the original DIVISION source, matches our live
VPX node/action tables exactly).
- source-ref/ read-only copies of the original DIVISION C (BIZREAD.C,
DPLTYPES.H, DPL.H) that define the formats.
- patha/ the "virtual VelociRender board": vrboard.py (24-action protocol
server), vrview.py (numpy software rasterizer, the reference),
vrview_gl.py (moderngl GPU backend, 832x512@60Hz), plus the
run/replay/regress tooling and evidence renders. Drives FLYK/BLADE/
Star Trek demos AND our btl4opt/rpl4opt game binaries.
- viewer/ WebGL archive generators (.py); prebuilt HTML/data regeneratable.
- samples/ small test models/textures.
- bt*.raw.bin real BTL4OPT arena wire captures (kept for offline renderer
testing/regression against OUR game).
.gitignore keeps the multi-hundred-MB demo capture dumps + debug logs +
regeneratable viewer bundles out of history (they stay on disk).
Phase 0 of the integration is validated: their board decodes our bt8 capture
with zero errors (3748 nodes, 507 instances, 4 mechs) and renders our arena
(terrain/dome/sky, correct Division DAC gamma). Plan + status in memory;
integration continues in emulator/RENDERER-COLLAB.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2.3 KiB
.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.