Fix errors
This commit is contained in:
86
CLAUDE.md
86
CLAUDE.md
@@ -661,11 +661,87 @@ PPIScope : public Scope (abstract) — shared PPI behavior:
|
||||
- Cursor range/bearing readout under scope (white text)
|
||||
- Bearing offset for boat mode (k/j)
|
||||
- Cursor range clamped to max range
|
||||
- Range rings and labels are beam-painted per sweep sector, NOT a static overlay;
|
||||
the sweep shader evaluates ring radii for the CURRENT max range at the moment
|
||||
each beam angle is rendered; the phosphor buffer retains whatever was last
|
||||
written, so old ring positions fade naturally as the sweep overwrites them with
|
||||
new geometry — no special transition code required
|
||||
- Range rings are beam-painted per sweep sector with P7 persistence and decay;
|
||||
however they are stored in the GAIN-INDEPENDENT G channel of the phosphor FBO
|
||||
(see PHOSPHOR FBO ARCHITECTURE below) so operator gain does not dim the rings
|
||||
- renderRingLabels() — virtual method (default no-op); concrete PPI scopes that
|
||||
have labelled range rings override this to render mile-distance text labels in
|
||||
P7 fresh-blue colour at a fixed bearing (RING_LABEL_BRG_DEG = 045°)
|
||||
|
||||
IMPLEMENTER CHECKLIST — required in every new PPIScope subclass:
|
||||
1. computeRingRadii(): multiply each normalised ring radius by
|
||||
GRAT_INNER_RING_FRAC (same as MarinePPIScope). Omitting this
|
||||
places the outer ring at the scope boundary where it is clipped
|
||||
and hidden behind the graticule. Target positions are scaled
|
||||
automatically by PhosphorRenderer::update(); ring radii are not.
|
||||
2. Override renderRingLabels() using the same pattern as
|
||||
MarinePPIScope::renderRingLabels() but with the scope's own
|
||||
ring-mile table. The base-class no-op produces no labels.
|
||||
The p7Color() fix, two-channel FBO gain-separation, and target
|
||||
position scaling are all automatic via the shared PhosphorRenderer
|
||||
and shaders — no per-scope action required for those.
|
||||
|
||||
==================================================================
|
||||
|
||||
PHOSPHOR FBO ARCHITECTURE
|
||||
|
||||
==================================================================
|
||||
|
||||
The phosphor FBO is GL_RG32F (two independent float channels):
|
||||
|
||||
R channel — signal energy
|
||||
Written by: target echoes in the sweep shader
|
||||
Multiplied by: u_gain in the display shader
|
||||
Effect: operator gain knob dims/brightens received echoes without
|
||||
affecting the sweep beam or range rings
|
||||
|
||||
G channel — timing/geometry energy
|
||||
Written by: range rings + sweep background glow in the sweep shader
|
||||
NOT multiplied by gain in the display shader
|
||||
Effect: rings always appear at a fixed brightness; the rotating
|
||||
sweep-line glow is always visible even at minimum gain
|
||||
|
||||
Both channels decay at the same P7 rate (P7_DECAY_RATE in settings.h).
|
||||
The display shader combines them: totalEnergy = max(R * gain, G).
|
||||
This produces the correct visual priority: a strong target echo always
|
||||
shows above the ring but a dim echo below gain threshold fades away
|
||||
while the ring stays steady.
|
||||
|
||||
RANGE POSITION NORMALISATION
|
||||
|
||||
All ring radii and target range values are normalised so that
|
||||
max-range maps to GRAT_INNER_RING_FRAC (0.915), NOT 1.0.
|
||||
|
||||
Normalised 1.0 is the outer edge of the phosphor circle (scope boundary).
|
||||
The bearing graticule overlay occupies 0.915 to 0.985 of scope radius.
|
||||
If max-range mapped to 1.0, the outer ring would sit at the scope
|
||||
boundary — half-clipped by the sweep shader's rng > 1.0 early-exit and
|
||||
visually hidden behind the graticule outer ring.
|
||||
|
||||
Mapping max-range → GRAT_INNER_RING_FRAC keeps all rings and targets
|
||||
within the clean active display area inside the bearing scale overlay.
|
||||
|
||||
Scale is applied in two places:
|
||||
1. PhosphorRenderer::update() — target range: × GRAT_INNER_RING_FRAC
|
||||
2. computeRingRadii() in each concrete PPI scope — ring radii: × GRAT_INNER_RING_FRAC
|
||||
|
||||
P7 COLOUR FUNCTION
|
||||
|
||||
p7Color() in phosphor.frag is a piecewise linear ramp over [0, 1]:
|
||||
e ≥ T_BLUE (0.82) → pure C_BLUE
|
||||
[T_GREEN, T_BLUE) → mix(C_GREEN, C_BLUE, normalised within range)
|
||||
[T_YGREE, T_GREEN) → mix(C_YGREE, C_GREEN, normalised within range)
|
||||
[T_DARK, T_YGREE) → mix(C_YELLW, C_YGREE, normalised within range)
|
||||
[0, T_DARK) → mix(C_BLACK, C_YELLW, normalised within range)
|
||||
|
||||
Each mix() factor is in [0, 1] and the function is continuous at every
|
||||
threshold boundary. An earlier version had each branch using the formula
|
||||
of the branch below it (off-by-one), which caused SWEEP_BACKGROUND_ENERGY
|
||||
= 0.10 to render as saturated yellow (factor 3.33) instead of dim
|
||||
yellow-green, producing an unwanted solid-yellow band behind the sweep.
|
||||
|
||||
==================================================================
|
||||
|
||||
|
||||
MarinePPIScope : public PPIScope
|
||||
- Sweep time: 4 seconds
|
||||
|
||||
Reference in New Issue
Block a user