diff --git a/scwx-qt/gl/radar.frag b/scwx-qt/gl/radar.frag index 38d16861..b4fd8e7e 100644 --- a/scwx-qt/gl/radar.frag +++ b/scwx-qt/gl/radar.frag @@ -5,9 +5,22 @@ precision mediump float; uniform sampler2D uTexture; -in vec2 texCoord; +flat in uint dataMoment; + +layout (location = 0) out vec4 fragColor; void main() { - gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f); + if (dataMoment < 126u) + { + fragColor = vec4(0.0f, 0.5f, 0.0f, 0.9f); + } + else if (dataMoment < 156u) + { + fragColor = vec4(1.0f, 0.75f, 0.0f, 0.9f); + } + else + { + fragColor = vec4(1.0f, 0.0f, 0.0f, 0.9f); + } } diff --git a/scwx-qt/gl/radar.vert b/scwx-qt/gl/radar.vert index 291780c7..8ea09c42 100644 --- a/scwx-qt/gl/radar.vert +++ b/scwx-qt/gl/radar.vert @@ -7,12 +7,12 @@ #define RAD2DEG 57.295779513082320876798156332941f layout (location = 0) in vec2 aLatLong; -layout (location = 1) in vec2 aTexCoord; +layout (location = 1) in uint aDataMoment; uniform mat4 uMVPMatrix; uniform vec2 uMapScreenCoord; -out vec2 texCoord; +flat out uint dataMoment; vec2 latLngToScreenCoordinate(in vec2 latLng) { @@ -25,8 +25,8 @@ vec2 latLngToScreenCoordinate(in vec2 latLng) void main() { - // Pass the texture coordinate to the fragment shader - texCoord = aTexCoord; + // Pass the coded data moment to the fragment shader + dataMoment = aDataMoment; vec2 p = latLngToScreenCoordinate(aLatLong) - uMapScreenCoord; diff --git a/scwx-qt/source/scwx/qt/map/radar_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_layer.cpp index 43c8f717..11b7f29d 100644 --- a/scwx-qt/source/scwx/qt/map/radar_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_layer.cpp @@ -44,11 +44,11 @@ public: std::shared_ptr radarView_; OpenGLFunctions& gl_; - ShaderProgram shaderProgram_; - GLint uMVPMatrixLocation_; - GLint uMapScreenCoordLocation_; - GLuint vbo_; - GLuint vao_; + ShaderProgram shaderProgram_; + GLint uMVPMatrixLocation_; + GLint uMapScreenCoordLocation_; + std::array vbo_; + GLuint vao_; GLsizeiptr numVertices_; }; @@ -89,19 +89,19 @@ void RadarLayer::initialize() << logPrefix_ << "Could not find uMapScreenCoord"; } - const std::vector& vertices = p->radarView_->vertices(); + const std::vector& vertices = p->radarView_->vertices(); + const std::vector& dataMoments8 = p->radarView_->data_moments8(); + const std::vector& dataMoments16 = p->radarView_->data_moments16(); - // Generate a vertex buffer object - gl.glGenBuffers(1, &p->vbo_); - - // Generate a vertex array object + // Generate and bind a vertex array object gl.glGenVertexArrays(1, &p->vao_); - - // Bind vertex array object gl.glBindVertexArray(p->vao_); - // Copy vertices array in a buffer for OpenGL to use - gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); + // Generate vertex buffer objects + gl.glGenBuffers(2, p->vbo_.data()); + + // Buffer vertices + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); timer.start(); gl.glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), @@ -111,12 +111,38 @@ void RadarLayer::initialize() BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Vertices buffered in " << timer.format(6, "%ws"); - // Set the vertex attributes pointers - gl.glVertexAttribPointer( - 0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), static_cast(0)); + gl.glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, static_cast(0)); gl.glEnableVertexAttribArray(0); - p->numVertices_ = vertices.size(); + // Buffer data moments + const GLvoid* data; + GLsizeiptr dataSize; + GLenum type; + + if (dataMoments8.size() > 0) + { + data = static_cast(dataMoments8.data()); + dataSize = dataMoments8.size() * sizeof(GLubyte); + type = GL_UNSIGNED_BYTE; + } + else + { + data = static_cast(dataMoments16.data()); + dataSize = dataMoments16.size() * sizeof(GLushort); + type = GL_UNSIGNED_SHORT; + } + + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + timer.start(); + gl.glBufferData(GL_ARRAY_BUFFER, dataSize, data, GL_STATIC_DRAW); + timer.stop(); + BOOST_LOG_TRIVIAL(debug) + << logPrefix_ << "Data moments buffered in " << timer.format(6, "%ws"); + + gl.glVertexAttribIPointer(1, 1, type, 0, static_cast(0)); + gl.glEnableVertexAttribArray(1); + + p->numVertices_ = vertices.size() / 2; } void RadarLayer::render(const QMapbox::CustomLayerRenderParameters& params) @@ -145,9 +171,7 @@ void RadarLayer::render(const QMapbox::CustomLayerRenderParameters& params) p->uMVPMatrixLocation_, 1, GL_FALSE, glm::value_ptr(uMVPMatrix)); gl.glBindVertexArray(p->vao_); - gl.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); - gl.glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } void RadarLayer::deinitialize() @@ -157,11 +181,11 @@ void RadarLayer::deinitialize() BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "deinitialize()"; gl.glDeleteVertexArrays(1, &p->vao_); - gl.glDeleteBuffers(1, &p->vbo_); + gl.glDeleteBuffers(2, p->vbo_.data()); p->uMVPMatrixLocation_ = GL_INVALID_INDEX; p->vao_ = GL_INVALID_INDEX; - p->vbo_ = GL_INVALID_INDEX; + p->vbo_ = {GL_INVALID_INDEX}; } static glm::vec2 diff --git a/scwx-qt/source/scwx/qt/view/radar_view.cpp b/scwx-qt/source/scwx/qt/view/radar_view.cpp index 62f85c08..d732772f 100644 --- a/scwx-qt/source/scwx/qt/view/radar_view.cpp +++ b/scwx-qt/source/scwx/qt/view/radar_view.cpp @@ -29,7 +29,9 @@ public: std::shared_ptr radarManager_; std::shared_ptr map_; - std::vector vertices_; + std::vector vertices_; + std::vector dataMoments8_; + std::vector dataMoments16_; }; RadarView::RadarView(std::shared_ptr radarManager, @@ -52,6 +54,16 @@ double RadarView::scale() const return p->map_->scale(); } +const std::vector& RadarView::data_moments8() const +{ + return p->dataMoments8_; +} + +const std::vector& RadarView::data_moments16() const +{ + return p->dataMoments16_; +} + const std::vector& RadarView::vertices() const { return p->vertices_; @@ -83,12 +95,33 @@ void RadarView::Initialize() auto momentData0 = radarData[0]->moment_data_block(blockType); + // Setup vertex vector std::vector& vertices = p->vertices_; const size_t radials = radarData.size(); const uint32_t gates = momentData0->number_of_data_moment_gates(); + size_t vIndex = 0; vertices.clear(); vertices.resize(radials * gates * VERTICES_PER_BIN * VALUES_PER_VERTEX); - size_t index = 0; + + // Setup data moment vector + std::vector& dataMoments8 = p->dataMoments8_; + std::vector& dataMoments16 = p->dataMoments16_; + size_t mIndex = 0; + + if (momentData0->data_word_size() == 8) + { + dataMoments16.resize(0); + dataMoments16.shrink_to_fit(); + + dataMoments8.resize(radials * gates * VERTICES_PER_BIN); + } + else + { + dataMoments8.resize(0); + dataMoments8.shrink_to_fit(); + + dataMoments16.resize(radials * gates * VERTICES_PER_BIN); + } // Compute threshold at which to display an individual bin const float scale = momentData0->scale(); @@ -111,6 +144,13 @@ void RadarView::Initialize() auto radialData = radarData[radial]; auto momentData = radarData[radial]->moment_data_block(blockType); + if (momentData0->data_word_size() != momentData->data_word_size()) + { + BOOST_LOG_TRIVIAL(warning) + << logPrefix_ << "Radial " << radial << " has different word size"; + continue; + } + // Compute gate interval const uint16_t dataMomentRange = momentData->data_moment_range_raw(); const uint16_t dataMomentInterval = @@ -129,31 +169,54 @@ void RadarView::Initialize() std::min(startGate + numberOfDataMomentGates * gateSize, common::MAX_DATA_MOMENT_GATES); - const uint8_t* dataMoments8 = nullptr; - const uint16_t* dataMoments16 = nullptr; + const uint8_t* dataMomentsArray8 = nullptr; + const uint16_t* dataMomentsArray16 = nullptr; if (momentData->data_word_size() == 8) { - dataMoments8 = + dataMomentsArray8 = reinterpret_cast(momentData->data_moments()); } else { - dataMoments16 = + dataMomentsArray16 = reinterpret_cast(momentData->data_moments()); } for (uint16_t gate = startGate, i = 0; gate + gateSize <= endGate; gate += gateSize, ++i) { - uint16_t dataValue = - (dataMoments8 != nullptr) ? dataMoments8[i] : dataMoments16[i]; + size_t vertexCount = (gate > 0) ? 6 : 3; - if (dataValue < snrThreshold) + // Store data moment value + if (dataMomentsArray8 != nullptr) { - continue; + uint8_t dataValue = dataMomentsArray8[i]; + if (dataValue < snrThreshold) + { + continue; + } + + for (size_t m = 0; m < vertexCount; m++) + { + dataMoments8[mIndex++] = dataMomentsArray8[i]; + } + } + else + { + uint16_t dataValue = dataMomentsArray16[i]; + if (dataValue < snrThreshold) + { + continue; + } + + for (size_t m = 0; m < vertexCount; m++) + { + dataMoments16[mIndex++] = dataMomentsArray16[i]; + } } + // Store vertices if (gate > 0) { const uint16_t baseCoord = gate - 1; @@ -170,23 +233,25 @@ void RadarView::Initialize() 2; size_t offset4 = offset3 + gateSize * 2; - vertices[index++] = coordinates[offset1]; - vertices[index++] = coordinates[offset1 + 1]; + vertices[vIndex++] = coordinates[offset1]; + vertices[vIndex++] = coordinates[offset1 + 1]; - vertices[index++] = coordinates[offset2]; - vertices[index++] = coordinates[offset2 + 1]; + vertices[vIndex++] = coordinates[offset2]; + vertices[vIndex++] = coordinates[offset2 + 1]; - vertices[index++] = coordinates[offset3]; - vertices[index++] = coordinates[offset3 + 1]; + vertices[vIndex++] = coordinates[offset3]; + vertices[vIndex++] = coordinates[offset3 + 1]; - vertices[index++] = coordinates[offset3]; - vertices[index++] = coordinates[offset3 + 1]; + vertices[vIndex++] = coordinates[offset3]; + vertices[vIndex++] = coordinates[offset3 + 1]; - vertices[index++] = coordinates[offset4]; - vertices[index++] = coordinates[offset4 + 1]; + vertices[vIndex++] = coordinates[offset4]; + vertices[vIndex++] = coordinates[offset4 + 1]; - vertices[index++] = coordinates[offset2]; - vertices[index++] = coordinates[offset2 + 1]; + vertices[vIndex++] = coordinates[offset2]; + vertices[vIndex++] = coordinates[offset2 + 1]; + + vertexCount = 6; } else { @@ -203,18 +268,30 @@ void RadarView::Initialize() 2; // TODO: Radar location - vertices[index++] = 38.6986f; - vertices[index++] = -90.6828f; + vertices[vIndex++] = 38.6986f; + vertices[vIndex++] = -90.6828f; - vertices[index++] = coordinates[offset1]; - vertices[index++] = coordinates[offset1 + 1]; + vertices[vIndex++] = coordinates[offset1]; + vertices[vIndex++] = coordinates[offset1 + 1]; - vertices[index++] = coordinates[offset2]; - vertices[index++] = coordinates[offset2 + 1]; + vertices[vIndex++] = coordinates[offset2]; + vertices[vIndex++] = coordinates[offset2 + 1]; + + vertexCount = 3; } } } - vertices.resize(index); + vertices.resize(vIndex); + + if (momentData0->data_word_size() == 8) + { + dataMoments8.resize(mIndex); + } + else + { + dataMoments16.resize(mIndex); + } + timer.stop(); BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Vertices calculated in " << timer.format(6, "%ws"); diff --git a/scwx-qt/source/scwx/qt/view/radar_view.hpp b/scwx-qt/source/scwx/qt/view/radar_view.hpp index 97374c00..829fe119 100644 --- a/scwx-qt/source/scwx/qt/view/radar_view.hpp +++ b/scwx-qt/source/scwx/qt/view/radar_view.hpp @@ -29,9 +29,11 @@ public: RadarView(RadarView&&) noexcept; RadarView& operator=(RadarView&&) noexcept; - double bearing() const; - double scale() const; - const std::vector& vertices() const; + double bearing() const; + double scale() const; + const std::vector& data_moments8() const; + const std::vector& data_moments16() const; + const std::vector& vertices() const; void Initialize();