Files
updated-radar/src/graticule.h
2026-04-23 08:05:03 -07:00

74 lines
2.1 KiB
C++

/*
* MIT License
* Author: Mark Allyn
*
* graticule.h — incandescent bearing graticule for PPI scopes.
*
* Renders:
* - Inner and outer bearing rings (circles)
* - One tick per degree; major ticks every 10 degrees
* - Text labels every GRAT_LABEL_INTERVAL_DEG degrees (15°)
*
* Also renders the yellow cursor arc + crossline when
* renderCursor() is called.
*
* All geometry is in screen pixels (top-left origin);
* the graticule.vert shader converts to NDC.
*/
#pragma once
#include <glad/glad.h>
#include <string>
#include <vector>
#include "settings.h"
// Forward-declared so graticule.h doesn't pull in FreeType.
class TextRenderer;
class Graticule {
public:
Graticule() = default;
~Graticule();
// Call after GL context is current.
// cx/cy: scope centre in screen pixels (top-left origin).
bool init(const std::string& shaderDir,
TextRenderer& tr,
float cx, float cy, float radius);
// Render the incandescent bearing graticule.
// intensity: 0-1 scales the graticule brightness.
// bearingOffset: degrees to rotate the display (Head-up mode).
void render(float viewportW, float viewportH,
float intensity, float bearingOffset = 0.0f) const;
// Render the yellow cursor overlay.
// brgDeg: cursor bearing (degrees true)
// rngNorm: cursor range, normalised 0-1 (1 = scope edge)
void renderCursor(float viewportW, float viewportH,
float brgDeg, float rngNorm) const;
private:
void buildRingGeometry();
void buildTickGeometry();
GLuint prog_ = 0;
GLuint ringVAO_ = 0, ringVBO_ = 0;
GLuint tickVAO_ = 0, tickVBO_ = 0;
GLuint cursVAO_ = 0, cursVBO_ = 0;
int ringVertCount_ = 0;
int tickVertCount_ = 0;
// Cursor geometry is rebuilt each frame (small, dynamic)
float cx_ = 0.f, cy_ = 0.f, r_ = 1.f;
TextRenderer* tr_ = nullptr;
// Pre-computed label screen positions (one per 15-degree step)
struct LabelPos {
float x, y;
char text[8];
};
std::vector<LabelPos> labels_;
};