From d2d6cabf06f34d0bfafb80429c708573af31d1af Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 8 Aug 2021 08:25:32 -0500 Subject: [PATCH] Add overlay layer with time --- scwx-qt/gl/overlay.frag | 9 + scwx-qt/gl/overlay.vert | 9 + scwx-qt/res/fonts/din1451alt.ttf | Bin 0 -> 32712 bytes scwx-qt/scwx-qt.cmake | 6 +- scwx-qt/scwx-qt.qrc | 3 + scwx-qt/source/scwx/qt/map/map_widget.cpp | 4 + scwx-qt/source/scwx/qt/map/overlay_layer.cpp | 223 +++++++++++++++++++ scwx-qt/source/scwx/qt/map/overlay_layer.hpp | 39 ++++ 8 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 scwx-qt/gl/overlay.frag create mode 100644 scwx-qt/gl/overlay.vert create mode 100644 scwx-qt/res/fonts/din1451alt.ttf create mode 100644 scwx-qt/source/scwx/qt/map/overlay_layer.cpp create mode 100644 scwx-qt/source/scwx/qt/map/overlay_layer.hpp diff --git a/scwx-qt/gl/overlay.frag b/scwx-qt/gl/overlay.frag new file mode 100644 index 00000000..b2fd78c6 --- /dev/null +++ b/scwx-qt/gl/overlay.frag @@ -0,0 +1,9 @@ +#version 330 core +uniform vec4 uColor; + +layout (location = 0) out vec4 fragColor; + +void main() +{ + fragColor = uColor; +} diff --git a/scwx-qt/gl/overlay.vert b/scwx-qt/gl/overlay.vert new file mode 100644 index 00000000..042a1d8a --- /dev/null +++ b/scwx-qt/gl/overlay.vert @@ -0,0 +1,9 @@ +#version 330 core +layout (location = 0) in vec2 aVertex; + +uniform mat4 uMVPMatrix; + +void main() +{ + gl_Position = uMVPMatrix * vec4(aVertex, 0.0f, 1.0f); +} diff --git a/scwx-qt/res/fonts/din1451alt.ttf b/scwx-qt/res/fonts/din1451alt.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4f46c82bb0adcfd2850f699f331bf233538f23bf GIT binary patch literal 32712 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

()g|`GQ~q!69c-!Q{=G&46b3| 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 + gl/overlay.frag + gl/overlay.vert gl/radar.frag gl/radar.vert gl/text.frag gl/text.vert + res/fonts/din1451alt.ttf diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index 1fa910e0..d15814ab 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -118,6 +119,8 @@ void MapWidget::AddLayers() // QMapboxGL::addCustomLayer will take ownership of the QScopedPointer QScopedPointer pHost( new RadarLayer(radarView, p->gl_)); + QScopedPointer pOverlayHost( + new OverlayLayer(radarView, p->gl_)); QString before = "ferry"; @@ -134,6 +137,7 @@ void MapWidget::AddLayers() p->map_->addCustomLayer("radar", pHost, before); RadarRangeLayer::Add(p->map_, before); + p->map_->addCustomLayer("overlay", pOverlayHost); } void MapWidget::keyPressEvent(QKeyEvent* ev) diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp new file mode 100644 index 00000000..a20356a8 --- /dev/null +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp @@ -0,0 +1,223 @@ +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace scwx +{ +namespace qt +{ +namespace map +{ + +static const std::string logPrefix_ = "[scwx::qt::map::overlay_layer] "; + +class OverlayLayerImpl +{ +public: + explicit OverlayLayerImpl(std::shared_ptr radarView, + gl::OpenGLFunctions& gl) : + radarView_(radarView), + gl_(gl), + textShader_(gl), + font_(util::Font::Create(":/res/fonts/din1451alt.ttf")), + shaderProgram_(gl), + uMVPMatrixLocation_(GL_INVALID_INDEX), + uColorLocation_(GL_INVALID_INDEX), + vbo_ {GL_INVALID_INDEX}, + vao_ {GL_INVALID_INDEX}, + texture_ {GL_INVALID_INDEX}, + numVertices_ {0}, + colorTableUpdated_(false), + plotUpdated_(true) + { + // TODO: Manage font at the global level, texture at the view level + } + ~OverlayLayerImpl() = default; + + std::shared_ptr radarView_; + gl::OpenGLFunctions& gl_; + + gl::TextShader textShader_; + std::shared_ptr font_; + gl::ShaderProgram shaderProgram_; + GLint uMVPMatrixLocation_; + GLint uColorLocation_; + GLuint vbo_; + GLuint vao_; + GLuint texture_; + + GLsizeiptr numVertices_; + + bool colorTableUpdated_; + bool plotUpdated_; +}; + +OverlayLayer::OverlayLayer(std::shared_ptr radarView, + gl::OpenGLFunctions& gl) : + p(std::make_unique(radarView, gl)) +{ +} +OverlayLayer::~OverlayLayer() = default; + +void OverlayLayer::initialize() +{ + BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "initialize()"; + + gl::OpenGLFunctions& gl = p->gl_; + + p->textShader_.Initialize(); + + // Load and configure overlay shader + p->shaderProgram_.Load(":/gl/overlay.vert", ":/gl/overlay.frag"); + + p->uMVPMatrixLocation_ = + gl.glGetUniformLocation(p->shaderProgram_.id(), "uMVPMatrix"); + if (p->uMVPMatrixLocation_ == -1) + { + BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Could not find uMVPMatrix"; + } + + p->uColorLocation_ = + gl.glGetUniformLocation(p->shaderProgram_.id(), "uColor"); + if (p->uColorLocation_ == -1) + { + BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Could not find uColor"; + } + + if (p->texture_ == GL_INVALID_INDEX) + { + p->texture_ = p->font_->GenerateTexture(gl); + } + + p->shaderProgram_.Use(); + + // Generate a vertex array object + gl.glGenVertexArrays(1, &p->vao_); + + // Generate vertex buffer objects + gl.glGenBuffers(1, &p->vbo_); + + gl.glBindVertexArray(p->vao_); + + // Bottom panel (dynamic sized) + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); + gl.glBufferData( + GL_ARRAY_BUFFER, sizeof(float) * 6 * 2, nullptr, GL_DYNAMIC_DRAW); + + gl.glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, static_cast(0)); + gl.glEnableVertexAttribArray(0); + + // Bottom panel color + gl.glUniform4f(p->uColorLocation_, 0.0f, 0.0f, 0.0f, 0.75f); + + connect(p->radarView_.get(), + &view::RadarView::PlotUpdated, + this, + &OverlayLayer::ReceivePlotUpdate); +} + +void OverlayLayer::render(const QMapbox::CustomLayerRenderParameters& params) +{ + gl::OpenGLFunctions& gl = p->gl_; + + static std::string plotTimeString; + + if (p->plotUpdated_) + { + using namespace std::chrono; + auto plotTime = time_point_cast(p->radarView_->PlotTime()); + + if (plotTime.time_since_epoch().count() != 0) + { + zoned_time zt = {current_zone(), plotTime}; + std::ostringstream os; + os << zt; + plotTimeString = os.str(); + } + + p->plotUpdated_ = false; + } + + glm::mat4 projection = glm::ortho(0.0f, + static_cast(params.width), + 0.0f, + static_cast(params.height)); + + p->shaderProgram_.Use(); + + gl.glUniformMatrix4fv( + p->uMVPMatrixLocation_, 1, GL_FALSE, glm::value_ptr(projection)); + + // Bottom panel vertices + float vertices[6][2] = {{0.0f, 0.0f}, + {0.0f, 24.0f}, + {static_cast(params.width), 0.0f}, // + // + {0.0f, 24.0f}, + {static_cast(params.width), 0.0f}, + {static_cast(params.width), 24.0f}}; + + // Draw vertices + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); + gl.glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); + gl.glDrawArrays(GL_TRIANGLES, 0, 6); + + // Render time + p->textShader_.RenderText(plotTimeString, + params.width - 7.0f, + 7.0f, + 16.0f, + projection, + boost::gil::rgba8_pixel_t(255, 255, 255, 204), + p->font_, + p->texture_, + gl::TextAlign::Right); + + SCWX_GL_CHECK_ERROR(); +} + +void OverlayLayer::deinitialize() +{ + gl::OpenGLFunctions& gl = p->gl_; + + BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "deinitialize()"; + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(1, &p->vbo_); + gl.glDeleteTextures(1, &p->texture_); + + p->uMVPMatrixLocation_ = GL_INVALID_INDEX; + p->uColorLocation_ = GL_INVALID_INDEX; + p->vao_ = GL_INVALID_INDEX; + p->vbo_ = {GL_INVALID_INDEX}; + p->texture_ = GL_INVALID_INDEX; + + disconnect(p->radarView_.get(), + &view::RadarView::PlotUpdated, + this, + &OverlayLayer::ReceivePlotUpdate); +} + +void OverlayLayer::ReceivePlotUpdate() +{ + p->plotUpdated_ = true; +} + +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.hpp b/scwx-qt/source/scwx/qt/map/overlay_layer.hpp new file mode 100644 index 00000000..8147fa3f --- /dev/null +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace map +{ + +class OverlayLayerImpl; + +class OverlayLayer : public QObject, public QMapbox::CustomLayerHostInterface +{ + Q_OBJECT + +public: + explicit OverlayLayer(std::shared_ptr radarView, + gl::OpenGLFunctions& gl); + ~OverlayLayer(); + + void initialize() override final; + void render(const QMapbox::CustomLayerRenderParameters&) override final; + void deinitialize() override final; + +public slots: + void ReceivePlotUpdate(); + +private: + std::unique_ptr p; +}; + +} // namespace map +} // namespace qt +} // namespace scwx