make shure that all changes were reflected in the .md file

This commit is contained in:
2026-06-20 22:42:02 -07:00
parent 200778af26
commit 2017732c1c
4 changed files with 253 additions and 2 deletions

View File

@@ -167,3 +167,41 @@ struct target_data_to_thread_1_structure {
uint32_t mmsi; // AIS unique identifier; ICAO hex address for aircraft uint32_t mmsi; // AIS unique identifier; ICAO hex address for aircraft
}; };
===============================================================================
CURRENT IMPLEMENTATION STATUS (stub phase)
Files: include/01_classes.h, src/01_classes.cpp
What is built:
RadarBase — abstract base class with three pure virtual methods:
render_left_panel() — renders radar description and keyboard control list
render_scope() — renders scope content (stub: radar name + "stub" label)
render_status_bar() — renders current control uniform values
Four stub subclasses, each overriding all three methods:
ChainHomeRadar (Ventnor, Isle of Wight)
MarineAScopeRadar (Community Boating Center, Bellingham Bay)
MarineTrafficRadar (center of Bellingham Bay)
PoliceboatRadar (Taylor Dock / Boulevard Park, Bellingham Bay)
One global instance of each subclass is declared in 01_classes.h and defined
in 01_classes.cpp: g_chain_home, g_marine_ascope, g_marine_traffic, g_police_boat.
What is NOT yet built (future components):
- Real scope rendering (radar sweep, target blips, graticule, range rings/ticks,
north indicator, P7 persistence layer, land/terrain background)
- Target data ingestion from Traffic Cop
- The Keyboard controls class (keyboard handling currently lives in the
static key_callback() function in src/main.cpp)
- The Traffic Cop class (Thread 2) — not yet started
- The Simulator class (Thread 3) — not yet started
- Per-frame update() method — the 30 Hz render loop in main.cpp calls
render_left_panel(), render_scope(), and render_status_bar() directly
Both target data structures (target_data_structure and
target_data_to_thread_1_structure) are defined in
include/data_structure_and_constants.h and will be used when the
Traffic Cop and Simulator components are built.

View File

@@ -69,3 +69,57 @@ field:
instructs the user to use the 1 and 2 keyboard keys to select the radar. The 1 key instructs the user to use the 1 and 2 keyboard keys to select the radar. The 1 key
steps forward in a circle and the 2 key steps backward and the enter key makes the steps forward in a circle and the 2 key steps backward and the enter key makes the
selection selection
===============================================================================
CURRENT IMPLEMENTATION STATUS
This spec covers two related but distinct pieces of the 02_text_description component:
A. Text renderer engine
Files: include/02_text_description.h, src/02_text_description.cpp
Status: COMPLETE
Implements the TextRenderer class using FreeType. Loads printable ASCII glyphs
(codes 32-126) from a TTF font into individual GL_RED textures and renders them
as textured quads into whichever viewport is currently active.
Public methods:
initialize_shaders() — compiles/links shaders/02_text_description_{vert,frag}.glsl
initialize_font(path, size) — loads a TTF font at a given pixel height
render_text() — renders a string at a viewport-local pixel coordinate
render_text_wrapped() — renders with automatic word-wrapping at a max pixel width
get_text_width() — returns the pixel width of a string at a given scale
set_projection(w, h) — sets the orthographic projection for a viewport
cleanup() — releases all GL resources and glyph textures
Two global instances are defined in src/02_text_description.cpp and declared
extern in the header:
g_text_renderer — loaded at FONT_SIZE_NORMAL (body text, controls, status bar)
g_text_renderer_large — loaded at FONT_SIZE_TITLE (panel titles, scope headings)
Font path and sizes are defined in include/settings.h:
FONT_PATH "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
FONT_SIZE_NORMAL 18 px
FONT_SIZE_TITLE 26 px
B. Left-panel text content for each radar
File: src/01_classes.cpp (render_left_panel() methods in each radar subclass)
Status: STUB — text content implemented; actual scope rendering is not yet done.
Each radar subclass in 01_classes renders:
- Radar title (large renderer, white)
- Location sub-header (small scale, white)
- 3-4 lines of description text (white)
- "--- CONTROLS ---" header (red) followed by per-control entries
(label in red, keystroke(s) in pink, on the same line)
- "1 - Return to Radar Selection" (yellow)
The intro scene (item 5 above) is rendered by render_intro_left_panel() in
src/main.cpp, which shows a welcome paragraph on the left panel and the
radar selection list centred in the scope viewport.
Status bar content for each radar is rendered by render_status_bar() in
src/01_classes.cpp, displaying current uniform values (intensity, sensitivity,
STC sensitivity/range, and radar-specific values such as max range, cursor
positions, radiogoniometer, or antenna bearing) in yellow.

View File

@@ -33,3 +33,65 @@ The following is suggested.
5. Run in a loop where every 30th of a second, update the selected radar. 5. Run in a loop where every 30th of a second, update the selected radar.
====================================================================== ======================================================================
CURRENT IMPLEMENTATION STATUS
File: src/main.cpp
Status: COMPLETE (stub phase)
The five-step flow described above is fully implemented in main():
Step 1 — parse_args()
Parses argv[] for radar names (chain_home, marine_ascope, marine_traffic,
police_boat). Sets radar_management[].available for each named radar.
With no arguments, all radars are made available.
STUB NOTE: The current build unconditionally sets operatable=1 for all four
radars before checking availability. When real radar components are built,
only the ones that are fully implemented should have operatable set to 1.
The check "available only if operatable" already works correctly in the code;
only the stub's operatable override needs to be updated.
Step 2 — GLFW / GLAD / OpenGL initialization
Creates a 1920x1080 window (WINDOW_WIDTH x WINDOW_HEIGHT from settings.h),
initialises GLAD, enables GL_DEBUG_OUTPUT (controlled by ENABLE_GL_DEBUG_OUTPUT
in settings.h), and sets global GL state (blending, no depth test).
Step 3 — Intro / selection screen
Renders the welcome text on the left panel (render_intro_left_panel()) and
the radar selection list centred in the scope viewport (render_radar_list()).
The status bar shows keyboard instructions (render_selection_status_bar()).
Step 4 — Selection loop
The GLFW key callback (key_callback) handles:
- Key 1: step selection forward
- Key 2: step selection backward
- ENTER: activate the highlighted radar; call reset_radar_controls()
- ESC: close the window
If exactly one radar is available, the application auto-activates it after
5 seconds (shows the selection screen during the countdown; breaks early
if ENTER is pressed).
Step 5 — Main render loop (~30 Hz)
Uses std::chrono::steady_clock to target a 1/30 s frame period.
Each frame:
- Polls GLFW events
- If SELECTION state: calls render_selection_screen()
- If OPERATING state: calls render_operating_screen(), which delegates
to g_active_radar->render_left_panel(), render_status_bar(),
render_scope() through the RadarBase virtual interface.
Additional features implemented:
- GL debug callback (gl_debug_callback) enabled via ENABLE_GL_DEBUG_OUTPUT
- Debug border-box renderer (draw_border_box) enabled via DEBUG_DRAW_WINDOW_BORDERS
in settings.h — draws white outlines around each panel for layout verification
- reset_radar_controls(): resets uniform_max_range, uniform_range_cursor,
uniform_bearing_cursor to defaults for the selected radar when it is activated
- Keyboard controls for all scope uniforms (intensity, sensitivity, STC, noise
filter, radiogoniometer, max range, range cursor, bearing cursor, antenna
rotation) are implemented in key_callback(); the controls are appropriately
restricted by radar type (e.g. noise filter only for PPI scopes)
Application state is tracked by AppState enum (SELECTION, OPERATING) in main.cpp.
The active radar object is pointed to by g_active_radar (a RadarBase*).
current_radar (global in global_data.cpp) holds the RADAR_* index of the active radar.

101
README.md
View File

@@ -1,3 +1,100 @@
# radar-simulation # radar-simulator
Source code for possible radar exhibit Museum exhibit software simulating 1940s1960s vintage radar systems.
## Project overview
This application runs as a full-screen interactive exhibit on a Geekom A8 Max
(AMD Ryzen 9 8945HS, Radeon 780M GPU, Ubuntu 25.10). Visitors can explore four
historical radar types by cycling through a selection screen and interacting with
keyboard controls.
**Four radar displays:**
| # | Name | Type | Location |
|---|------|------|----------|
| 1 | Chain Home | A-scope (WWII, 1940s) | RAF Ventnor, Isle of Wight |
| 2 | Marine A-Scope | A-scope (pre-PPI, manually steered dish) | Community Boating Center, Bellingham Bay WA |
| 3 | Marine Traffic Control | PPI scope | Center of Bellingham Bay WA |
| 4 | Police Boat | PPI scope (moving platform) | Taylor Dock / Boulevard Park, Bellingham Bay WA |
## Tech stack
- **Language:** C++20
- **Graphics:** OpenGL 4.3 Core, GLFW, GLAD
- **Text:** FreeType 2
- **Maps/LIDAR:** GDAL (libgdal-dev)
- **Database:** PostgreSQL (database: radar, user: radar)
- **Build:** CMake
## Build
```bash
mkdir -p build && cd build
cmake ..
make -j$(nproc)
```
The executable is `build/radar_simulator`.
## Running
```bash
# All four radars available
./radar_simulator
# Specific radars only
./radar_simulator chain_home marine_ascope
./radar_simulator marine_traffic police_boat
```
If only one radar is specified, it auto-activates after 5 seconds.
## Screen layout
The window is 1920×1080 and is divided into three areas:
- **Left text panel** (upper-left, 500 px wide): radar description and keyboard controls
- **Status bar** (lower-left, 500×250 px): current control values in yellow
- **Scope** (right side, square, full height): radar display
## Keyboard controls
| Key | Action |
|-----|--------|
| **1** | Step forward in radar selection (or return to selection when operating) |
| **2** | Step backward in radar selection |
| **ENTER** | Activate selected radar |
| **ESC** | Exit |
| **3 / 4** | Intensity lower / higher |
| **5 / 6** | Receiver sensitivity lower / higher |
| **Q / W** | STC sensitivity lower / higher |
| **E / R** | STC range lower / higher |
| **T / Y** | Rain noise filter lower / higher (PPI scopes only) |
| **U / I** | Radiogoniometer left / right (Chain Home only) |
| **O / P** | Max range step down / up (all except Chain Home) |
| **A / S** | Range cursor lower / higher (PPI scopes only) |
| **D / F** | Bearing cursor CCW / CW (PPI scopes only) |
| **G / H** | Antenna rotation CCW / CW (Marine A-Scope only) |
## Component .md files
Each component has a specification and status file:
- `01_classes.md` — class hierarchy (RadarBase + 4 subclasses; stubs built)
- `02_text_description.md` — text renderer and left-panel text content (complete)
- `03_setup_and_radar_selection.md` — startup, selection loop, main render loop (complete)
## Current build state
The initialization and radar-management infrastructure is complete:
- Four stub radar subclasses render description text, keyboard control lists,
and current control values in the status bar.
- The scope area shows the radar name with a `[stub]` label — no actual radar
simulation is drawn yet.
- All keyboard controls update CPU globals; uniforms will be pushed to shaders
as each scope component is built.
Real radar scope rendering (sweep, targets, graticule, range rings/ticks,
terrain, P7 phosphor persistence) will be added one radar at a time.