Skip to content

Battlefield: the map stays on the scenery while you zoom - #92

Merged
ptescher merged 1 commit into
masterfrom
towers-zoom
Nov 9, 2026
Merged

ptescher merged 1 commit into
masterfrom
towers-zoom

Conversation

@ptescher

@ptescher ptescher commented Nov 9, 2026

Copy link
Copy Markdown
Owner

The bug

In the Towers commander app (and the console's battlefield view), the map drawn over the 3D picture (circles, bases, drones, the field's ring) slid against the scenery while zooming or panning, then snapped back when the camera stopped.

Why

The 3D view sends the app each picture with the camera it was rendered from, and the app lays its map on the picture with that camera. But a GPU readback trails the camera by a frame or more, and the number varies. The view guessed: "the second newest camera". While the camera moved, every frame's camera was different, so the guess was often a frame off. The map was then drawn for a camera the picture wasn't taken from.

The fix

steady_request: a picture goes out only when the last four requests (camera plus size) are the same, so its camera is certain. While the camera moves, the app keeps the last picture, with its map correctly on it; the new picture arrives once the camera has been still for a few frames.

The size check now also uses the size the view actually renders (capped at MAX_SIZE). Before, a battlefield bigger than that never got a picture.

Tests

  • Red first: a_picture_goes_out_only_when_its_camera_is_sure (moving camera: none; still camera: the picture; a picture from before a resize: none; a battlefield bigger than the cap: the capped picture).
  • The commander app's «The battlefield shows the valley in 3D» passes: pictures still arrive.
  • Clippy (-D warnings) and fmt are clean.
  • Not tested automatically: how it feels to zoom. Please try the wheel with the drone cameras on.

Not changed

The fog of war is drawn on a coarse grid, which gives the blocky light and dark shapes in the screenshot. That's how it's drawn by design, not this bug.

🤖 Generated with Claude Code

The 3D view sends the app each picture of the battlefield with the
camera it was rendered from, and the app lays its map (circles, bases,
drones) on the picture with that camera. The readback trails the camera
by a frame or more, a number that varies, and the view guessed: the
second newest camera. While the commander zoomed or panned, the camera
changed every frame, the guess was often a frame off, and the map slid
over the scenery until the camera stopped ('the UI zooms separately
from the scenery').

steady_request sends a picture only when the last four requests are the
same: then its camera is sure. While the camera moves, the app keeps the
last picture with its map on it. The size check also uses the size the
view renders (capped at MAX_SIZE): a battlefield bigger than that never
got a picture.

Red: a_picture_goes_out_only_when_its_camera_is_sure (no steady_request).
The commander app's «The battlefield shows the valley in 3D» passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptescher
ptescher merged commit e36cfed into master Nov 9, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant