From c6a323247d90f39065c8f7e918c618fdacbbad57 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Thu, 22 Jul 2021 21:52:58 -0500 Subject: [PATCH] Calculate coordinates in parallel and eliminate duplication, in advance of vertices --- scwx-qt/scwx-qt.cmake | 1 + scwx-qt/source/scwx/qt/map/radar_layer.cpp | 132 +++++++++++++-------- 2 files changed, 81 insertions(+), 52 deletions(-) diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 0e46e74a..bf1a19d8 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -103,6 +103,7 @@ target_include_directories(scwx-qt PRIVATE ${scwx-qt_SOURCE_DIR}/source target_link_libraries(scwx-qt PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::OpenGLWidgets Boost::log + Boost::timer qmapboxgl opengl32 GeographicLib::GeographicLib diff --git a/scwx-qt/source/scwx/qt/map/radar_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_layer.cpp index 29e79cf6..39c2357e 100644 --- a/scwx-qt/source/scwx/qt/map/radar_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_layer.cpp @@ -1,9 +1,13 @@ #include #include +#include + #include #include +#include +#include #include #include #include @@ -15,6 +19,9 @@ namespace scwx namespace qt { +static constexpr uint32_t MAX_RADIALS = 720; +static constexpr uint32_t MAX_DATA_MOMENT_GATES = 1840; + static const std::string logPrefix_ = "[scwx::qt::map::radar_layer] "; static glm::vec2 @@ -70,6 +77,9 @@ void RadarLayer::initialize() QOpenGLFunctions_3_3_Core& gl = p->gl_; + boost::timer::cpu_timer timer; + + // Load and configure radar shader p->shaderProgram_.Load(":/gl/radar.vert", ":/gl/radar.frag"); p->uMVPMatrixLocation_ = @@ -87,82 +97,95 @@ void RadarLayer::initialize() << logPrefix_ << "Could not find uMapScreenCoord"; } - constexpr uint16_t MAX_RADIALS = 720; - constexpr uint16_t MAX_DATA_MOMENT_GATES = 1840; - - const QMapbox::Coordinate radar(38.6986, -90.6828); - const QPointF radarScreen = p->map_->pixelForCoordinate(radar); - - static std::array - vertices; - - constexpr float angleDelta = 0.5f; - constexpr float angleDeltaH = angleDelta / 2.0f; - - float angle1 = -angleDeltaH; - float angle2 = angleDeltaH; - - GLsizeiptr index = 0; + // Calculate coordinates + static std::array + coordinates; GeographicLib::Geodesic geodesic(GeographicLib::Constants::WGS84_a(), GeographicLib::Constants::WGS84_f()); - p->scale_ = p->map_->scale(); - p->bearing_ = p->map_->bearing(); + const QMapbox::Coordinate radar(38.6986, -90.6828); + auto radialGates = + boost::irange(0, MAX_RADIALS * MAX_DATA_MOMENT_GATES); - for (uint16_t azimuth = 0; azimuth < 720; ++azimuth) + timer.start(); + std::for_each( + std::execution::par_unseq, + radialGates.begin(), + radialGates.end(), + [&](uint32_t radialGate) { + const uint16_t gate = + static_cast(radialGate % MAX_DATA_MOMENT_GATES); + const uint16_t radial = + static_cast(radialGate / MAX_DATA_MOMENT_GATES); + + const float angle = radial * 0.5f - 0.25f; + const float range = (gate + 1) * 250.0f; + const size_t offset = radialGate * 2; + + double latitude; + double longitude; + + geodesic.Direct( + radar.first, radar.second, angle, range, latitude, longitude); + + coordinates[offset] = latitude; + coordinates[offset + 1] = longitude; + }); + timer.stop(); + BOOST_LOG_TRIVIAL(debug) + << "Coordinates calculated in " << timer.format(6, "%ws"); + + // Calculate vertices + static std::array + vertices; + GLsizeiptr index = 0; + + timer.start(); + for (uint16_t radial = 0; radial < 720; ++radial) { const float dataMomentRange = 2.125f * 1000.0f; const float dataMomentInterval = 0.25f * 1000.0f; const float dataMomentIntervalH = dataMomentInterval * 0.5f; const float snrThreshold = 2.0f; + const uint16_t startGate = 7; const uint16_t numberOfDataMomentGates = 1832; + const uint16_t endGate = std::min( + numberOfDataMomentGates + startGate, MAX_DATA_MOMENT_GATES - 1); - float range1 = dataMomentRange - dataMomentIntervalH; - float range2 = range1 + dataMomentInterval; - - for (uint16_t gate = 0; gate < numberOfDataMomentGates; ++gate) + for (uint16_t gate = startGate; gate < endGate; ++gate) { - double lat[4]; - double lon[4]; + size_t offset1 = (radial * MAX_DATA_MOMENT_GATES + gate) * 2; + size_t offset2 = offset1 + 2; + size_t offset3 = + (((radial + 1) % MAX_RADIALS) * MAX_DATA_MOMENT_GATES + gate) * 2; + size_t offset4 = offset3 + 2; - // TODO: Optimize - geodesic.Direct( - radar.first, radar.second, angle1, range1, lat[0], lon[0]); - geodesic.Direct( - radar.first, radar.second, angle1, range2, lat[1], lon[1]); - geodesic.Direct( - radar.first, radar.second, angle2, range1, lat[2], lon[2]); - geodesic.Direct( - radar.first, radar.second, angle2, range2, lat[3], lon[3]); + vertices[index++] = coordinates[offset1]; + vertices[index++] = coordinates[offset1 + 1]; - vertices[index++] = lat[0]; - vertices[index++] = lon[0]; + vertices[index++] = coordinates[offset2]; + vertices[index++] = coordinates[offset2 + 1]; - vertices[index++] = lat[1]; - vertices[index++] = lon[1]; + vertices[index++] = coordinates[offset3]; + vertices[index++] = coordinates[offset3 + 1]; - vertices[index++] = lat[2]; - vertices[index++] = lon[2]; + vertices[index++] = coordinates[offset3]; + vertices[index++] = coordinates[offset3 + 1]; - vertices[index++] = lat[2]; - vertices[index++] = lon[2]; + vertices[index++] = coordinates[offset4]; + vertices[index++] = coordinates[offset4 + 1]; - vertices[index++] = lat[3]; - vertices[index++] = lon[3]; - - vertices[index++] = lat[1]; - vertices[index++] = lon[1]; - - range1 += dataMomentInterval; - range2 += dataMomentInterval; + vertices[index++] = coordinates[offset2]; + vertices[index++] = coordinates[offset2 + 1]; } - angle1 += angleDelta; - angle2 += angleDelta; break; } + timer.stop(); + BOOST_LOG_TRIVIAL(debug) + << "Vertices calculated in " << timer.format(6, "%ws"); // Generate a vertex buffer object gl.glGenBuffers(1, &p->vbo_); @@ -175,10 +198,14 @@ void RadarLayer::initialize() // Copy vertices array in a buffer for OpenGL to use gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); + timer.start(); gl.glBufferData(GL_ARRAY_BUFFER, index * sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW); + timer.stop(); + BOOST_LOG_TRIVIAL(debug) + << "Vertices buffered in " << timer.format(6, "%ws"); // Set the vertex attributes pointers gl.glVertexAttribPointer( @@ -186,6 +213,7 @@ void RadarLayer::initialize() gl.glEnableVertexAttribArray(0); p->numVertices_ = index; + p->bearing_ = p->map_->bearing(); } void RadarLayer::render(const QMapbox::CustomLayerRenderParameters& params)