perf(ui): F8-12 — pixel-space planet sizing + single-copy label/outline layers (#55)
Tests · UI / test (push) Has been cancelled
Tests · UI / test (pull_request) Successful in 3m20s

* Planet size formula moves to pixel-space:
  `pointRadiusBasePx = 2 + 2 * cbrt(size / SIZE_NORMALIZER)`. The
  on-screen disc now reads ~4-7 px at the reference zoom regardless
  of how large the world rectangle is — the previous `world-units`
  formulation blew up on small maps and made Source-class planets
  swallow their neighbours.
* Labels + outlines live in the origin copy only. The 9× replication
  across torus copies was the dominant cost on a 100+ planet map
  (Pixi.Text creation + Graphics rebuilds on every zoom step); the
  origin-copy layout is what the camera-wrap listener guarantees
  the user actually sees.
* `setPlanetLabels` and `setPlanetOutlines` skip Pixi-object
  rebuilds when the input fingerprint is unchanged — toggle flips
  and selection changes now keep the existing Text / Graphics
  instances alive and only repaint the affected pieces.
* `renderer.md` updated to the new contract.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-28 00:39:19 +02:00
parent 75a4211373
commit 6996a79286
6 changed files with 218 additions and 167 deletions
+13 -9
View File
@@ -73,14 +73,17 @@ and `displayPointRadiusWorld` (in `src/map/world.ts`) compute those
world-space values; the hit-test reads the same helpers so the click
zone always matches the visible footprint.
`style.pointRadiusWorld` is the alternative sizing rule for planet
`style.pointRadiusBasePx` is the alternative sizing rule for planet
discs with a known `size`: the renderer treats the base radius as
world units and softens its growth with the camera scale through
`PLANET_SIZE_ZOOM_ALPHA` (0.33). At `scale = scaleRef` (the
"whole world fits the viewport" zoom) the visible radius equals the
base radius; zooming in grows it sub-linearly so on-screen pixel
size scales as `scale^α`. Setting both `pointRadiusWorld` and
`pointRadiusPx` ignores the pixel-space field.
on-screen pixels **at the reference scale** and grows its on-screen
pixel size with the camera scale through `PLANET_SIZE_ZOOM_ALPHA`
(0.33). At `scale = scaleRef` (the "whole world fits the viewport"
zoom) the visible disc reads at `pointRadiusBasePx` screen pixels;
zooming in grows it as `scale^α` instead of linearly. This keeps
known-size planets sane on every world rectangle — a 4000×4000 map
and a 100×100 map both default to the same on-screen size. Setting
both `pointRadiusBasePx` and `pointRadiusPx` ignores the pixel-space
field.
Default hit slop in screen pixels: point=8, circle=6, line=6.
These are touch-ergonomic defaults; per-primitive `hitSlopPx > 0`
@@ -168,8 +171,9 @@ Per-primitive distance:
small ergonomic margin on top. `visibleRadiusWorld` comes from
`displayPointRadiusWorld` (F8-12 / #28 + #31): pixel-space
`pointRadiusPx / scale` for unidentified planets and most ship
groups, softened-by-zoom `pointRadiusWorld * (scale / scaleRef)^(α-1)`
for planets with a known `size`. `pointRadiusPx` defaults to
groups, softened-by-zoom
`pointRadiusBasePx * (scale / scaleRef)^α / scale` for planets
with a known `size`. `pointRadiusPx` defaults to
`DEFAULT_POINT_RADIUS_PX = 3` when neither field is set.
- **Filled circle**: `distSq ≤ (radius + slopWorld)²` where
`radius` is in world units. The circle counts as filled when