Update only dirty lines

This commit is contained in:
Dan Paulat 2024-07-07 11:51:53 -05:00
parent 803dfdd455
commit 037e0922b0
3 changed files with 268 additions and 94 deletions

View file

@ -6,6 +6,7 @@
#include <execution> #include <execution>
#include <boost/unordered/unordered_flat_set.hpp>
#include <units/angle.h> #include <units/angle.h>
namespace scwx namespace scwx
@ -25,11 +26,13 @@ static constexpr size_t kNumTriangles = kNumRectangles * 2;
static constexpr size_t kVerticesPerTriangle = 3; static constexpr size_t kVerticesPerTriangle = 3;
static constexpr size_t kVerticesPerRectangle = kVerticesPerTriangle * 2; static constexpr size_t kVerticesPerRectangle = kVerticesPerTriangle * 2;
static constexpr size_t kPointsPerVertex = 9; static constexpr size_t kPointsPerVertex = 9;
static constexpr size_t kBufferLength = static constexpr size_t kLineBufferLength_ =
kNumTriangles * kVerticesPerTriangle * kPointsPerVertex; kNumTriangles * kVerticesPerTriangle * kPointsPerVertex;
// Threshold, start time, end time // Threshold, start time, end time, displayed
static constexpr std::size_t kIntegersPerVertex_ = 3; static constexpr std::size_t kIntegersPerVertex_ = 4;
static constexpr std::size_t kIntegerBufferLength_ =
kNumTriangles * kVerticesPerTriangle * kIntegersPerVertex_;
struct GeoLineDrawItem struct GeoLineDrawItem
{ {
@ -81,6 +84,12 @@ public:
void BufferLine(const std::shared_ptr<const GeoLineDrawItem>& di); void BufferLine(const std::shared_ptr<const GeoLineDrawItem>& di);
void Update(); void Update();
void UpdateBuffers(); void UpdateBuffers();
void UpdateModifiedLineBuffers();
void UpdateSingleBuffer(const std::shared_ptr<const GeoLineDrawItem>& di,
std::size_t lineIndex,
std::vector<float>& linesBuffer,
std::vector<GLint>& integerBuffer,
std::vector<LineHoverEntry>& hoverLines);
std::shared_ptr<GlContext> context_; std::shared_ptr<GlContext> context_;
@ -88,6 +97,8 @@ public:
bool dirty_ {false}; bool dirty_ {false};
bool thresholded_ {false}; bool thresholded_ {false};
boost::unordered_flat_set<std::shared_ptr<GeoLineDrawItem>> dirtyLines_ {};
std::chrono::system_clock::time_point selectedTime_ {}; std::chrono::system_clock::time_point selectedTime_ {};
std::mutex lineMutex_ {}; std::mutex lineMutex_ {};
@ -137,7 +148,6 @@ void GeoLines::set_thresholded(bool thresholded)
void GeoLines::Initialize() void GeoLines::Initialize()
{ {
gl::OpenGLFunctions& gl = p->context_->gl(); gl::OpenGLFunctions& gl = p->context_->gl();
auto& gl30 = p->context_->gl30();
p->shaderProgram_ = p->context_->GetShaderProgram( p->shaderProgram_ = p->context_->GetShaderProgram(
{{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"},
@ -158,8 +168,10 @@ void GeoLines::Initialize()
gl.glBindVertexArray(p->vao_); gl.glBindVertexArray(p->vao_);
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]);
gl.glBufferData( gl.glBufferData(GL_ARRAY_BUFFER,
GL_ARRAY_BUFFER, sizeof(float) * kBufferLength, nullptr, GL_DYNAMIC_DRAW); sizeof(float) * kLineBufferLength_,
nullptr,
GL_DYNAMIC_DRAW);
// aLatLong // aLatLong
gl.glVertexAttribPointer(0, gl.glVertexAttribPointer(0,
@ -217,7 +229,13 @@ void GeoLines::Initialize()
gl.glEnableVertexAttribArray(6); gl.glEnableVertexAttribArray(6);
// aDisplayed // aDisplayed
gl30.glVertexAttribI1i(7, 1); gl.glVertexAttribPointer(7,
1,
GL_INT,
GL_FALSE,
kIntegersPerVertex_ * sizeof(GLint),
reinterpret_cast<void*>(3 * sizeof(float)));
gl.glEnableVertexAttribArray(7);
p->dirty_ = true; p->dirty_ = true;
} }
@ -280,7 +298,7 @@ void GeoLines::Deinitialize()
gl::OpenGLFunctions& gl = p->context_->gl(); gl::OpenGLFunctions& gl = p->context_->gl();
gl.glDeleteVertexArrays(1, &p->vao_); gl.glDeleteVertexArrays(1, &p->vao_);
gl.glDeleteBuffers(2, p->vbo_.data()); gl.glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data());
std::unique_lock lock {p->lineMutex_}; std::unique_lock lock {p->lineMutex_};
@ -313,44 +331,95 @@ void GeoLines::SetLineLocation(const std::shared_ptr<GeoLineDrawItem>& di,
float longitude1, float longitude1,
float latitude2, float latitude2,
float longitude2) float longitude2)
{
if (di->latitude1_ != latitude1 || di->longitude1_ != longitude1 ||
di->latitude2_ != latitude1 || di->longitude2_ != longitude1)
{ {
di->latitude1_ = latitude1; di->latitude1_ = latitude1;
di->longitude1_ = longitude1; di->longitude1_ = longitude1;
di->latitude2_ = latitude2; di->latitude2_ = latitude2;
di->longitude2_ = longitude2; di->longitude2_ = longitude2;
p->dirtyLines_.insert(di);
}
} }
void GeoLines::SetLineModulate(const std::shared_ptr<GeoLineDrawItem>& di, void GeoLines::SetLineModulate(const std::shared_ptr<GeoLineDrawItem>& di,
boost::gil::rgba8_pixel_t modulate) boost::gil::rgba8_pixel_t modulate)
{ {
di->modulate_ = {modulate[0] / 255.0f, boost::gil::rgba32f_pixel_t newModulate = {modulate[0] / 255.0f,
modulate[1] / 255.0f, modulate[1] / 255.0f,
modulate[2] / 255.0f, modulate[2] / 255.0f,
modulate[3] / 255.0f}; modulate[3] / 255.0f};
if (di->modulate_ != newModulate)
{
di->modulate_ = newModulate;
p->dirtyLines_.insert(di);
}
} }
void GeoLines::SetLineModulate(const std::shared_ptr<GeoLineDrawItem>& di, void GeoLines::SetLineModulate(const std::shared_ptr<GeoLineDrawItem>& di,
boost::gil::rgba32f_pixel_t modulate) boost::gil::rgba32f_pixel_t modulate)
{
if (di->modulate_ != modulate)
{ {
di->modulate_ = modulate; di->modulate_ = modulate;
p->dirtyLines_.insert(di);
}
} }
void GeoLines::SetLineWidth(const std::shared_ptr<GeoLineDrawItem>& di, void GeoLines::SetLineWidth(const std::shared_ptr<GeoLineDrawItem>& di,
float width) float width)
{
if (di->width_ != width)
{ {
di->width_ = width; di->width_ = width;
p->dirtyLines_.insert(di);
}
} }
void GeoLines::SetLineVisible(const std::shared_ptr<GeoLineDrawItem>& di, void GeoLines::SetLineVisible(const std::shared_ptr<GeoLineDrawItem>& di,
bool visible) bool visible)
{
if (di->visible_ != visible)
{ {
di->visible_ = visible; di->visible_ = visible;
p->dirtyLines_.insert(di);
}
} }
void GeoLines::SetLineHoverText(const std::shared_ptr<GeoLineDrawItem>& di, void GeoLines::SetLineHoverText(const std::shared_ptr<GeoLineDrawItem>& di,
const std::string& text) const std::string& text)
{
if (di->hoverText_ != text)
{ {
di->hoverText_ = text; di->hoverText_ = text;
p->dirtyLines_.insert(di);
}
}
void GeoLines::SetLineStartTime(const std::shared_ptr<GeoLineDrawItem>& di,
std::chrono::system_clock::time_point startTime)
{
if (di->startTime_ != startTime)
{
di->startTime_ =
std::chrono::time_point_cast<std::chrono::seconds,
std::chrono::system_clock>(startTime);
p->dirtyLines_.insert(di);
}
}
void GeoLines::SetLineEndTime(const std::shared_ptr<GeoLineDrawItem>& di,
std::chrono::system_clock::time_point endTime)
{
if (di->endTime_ != endTime)
{
di->endTime_ =
std::chrono::time_point_cast<std::chrono::seconds,
std::chrono::system_clock>(endTime);
p->dirtyLines_.insert(di);
}
} }
void GeoLines::FinishLines() void GeoLines::FinishLines()
@ -379,20 +448,63 @@ void GeoLines::FinishLines()
void GeoLines::Impl::UpdateBuffers() void GeoLines::Impl::UpdateBuffers()
{ {
newLinesBuffer_.clear(); newLinesBuffer_.clear();
newLinesBuffer_.reserve(newLineList_.size() * kBufferLength); newLinesBuffer_.reserve(newLineList_.size() * kLineBufferLength_);
newIntegerBuffer_.clear(); newIntegerBuffer_.clear();
newIntegerBuffer_.reserve(newLineList_.size() * kVerticesPerRectangle * newIntegerBuffer_.reserve(newLineList_.size() * kVerticesPerRectangle *
kIntegersPerVertex_); kIntegersPerVertex_);
newHoverLines_.clear(); newHoverLines_.clear();
for (auto& di : newLineList_) for (std::size_t i = 0; i < newLineList_.size(); ++i)
{ {
BufferLine(di); auto& di = newLineList_[i];
// Update line buffer
UpdateSingleBuffer(
di, i, newLinesBuffer_, newIntegerBuffer_, newHoverLines_);
}
// All lines have been updated
dirtyLines_.clear();
}
void GeoLines::Impl::UpdateModifiedLineBuffers()
{
// Update buffers for modified lines
for (auto& di : dirtyLines_)
{
// Find modified line in the current list
auto it =
std::find(currentLineList_.cbegin(), currentLineList_.cend(), di);
// Ignore invalid lines
if (it == currentLineList_.cend())
{
continue;
}
auto lineIndex = std::distance(currentLineList_.cbegin(), it);
UpdateSingleBuffer(di,
lineIndex,
currentLinesBuffer_,
currentIntegerBuffer_,
currentHoverLines_);
}
// Clear list of modified lines
if (!dirtyLines_.empty())
{
dirtyLines_.clear();
dirty_ = true;
} }
} }
void GeoLines::Impl::BufferLine( void GeoLines::Impl::UpdateSingleBuffer(
const std::shared_ptr<const GeoLineDrawItem>& di) const std::shared_ptr<const GeoLineDrawItem>& di,
std::size_t lineIndex,
std::vector<float>& lineBuffer,
std::vector<GLint>& integerBuffer,
std::vector<LineHoverEntry>& hoverLines)
{ {
// Threshold value // Threshold value
units::length::nautical_miles<double> threshold = di->threshold_; units::length::nautical_miles<double> threshold = di->threshold_;
@ -438,9 +550,11 @@ void GeoLines::Impl::BufferLine(
const float mc2 = di->modulate_[2]; const float mc2 = di->modulate_[2];
const float mc3 = di->modulate_[3]; const float mc3 = di->modulate_[3];
// Update buffers // Visibility
newLinesBuffer_.insert(newLinesBuffer_.end(), const GLint v = static_cast<GLint>(di->visible_);
{
// Initiailize line data
const auto lineData = {
// Line // Line
lat1, lon1, lx, by, mc0, mc1, mc2, mc3, a, // BL lat1, lon1, lx, by, mc0, mc1, mc2, mc3, a, // BL
lat2, lon2, lx, ty, mc0, mc1, mc2, mc3, a, // TL lat2, lon2, lx, ty, mc0, mc1, mc2, mc3, a, // TL
@ -448,28 +562,53 @@ void GeoLines::Impl::BufferLine(
lat1, lon1, rx, by, mc0, mc1, mc2, mc3, a, // BR lat1, lon1, rx, by, mc0, mc1, mc2, mc3, a, // BR
lat2, lon2, rx, ty, mc0, mc1, mc2, mc3, a, // TR lat2, lon2, rx, ty, mc0, mc1, mc2, mc3, a, // TR
lat2, lon2, lx, ty, mc0, mc1, mc2, mc3, a // TL lat2, lon2, lx, ty, mc0, mc1, mc2, mc3, a // TL
}); };
newIntegerBuffer_.insert(newIntegerBuffer_.end(), const auto integerData = {thresholdValue, startTime, endTime, v,
{thresholdValue, thresholdValue, startTime, endTime, v,
startTime, thresholdValue, startTime, endTime, v,
endTime, thresholdValue, startTime, endTime, v,
thresholdValue, thresholdValue, startTime, endTime, v,
startTime, thresholdValue, startTime, endTime, v};
endTime,
thresholdValue,
startTime,
endTime,
thresholdValue,
startTime,
endTime,
thresholdValue,
startTime,
endTime,
thresholdValue,
startTime,
endTime});
if (!di->hoverText_.empty()) // Buffer position data
auto lineBufferPosition = lineBuffer.end();
auto lineBufferOffset = lineIndex * kLineBufferLength_;
auto integerBufferPosition = integerBuffer.end();
auto integerBufferOffset = lineIndex * kIntegerBufferLength_;
if (lineBufferOffset < lineBuffer.size())
{
lineBufferPosition = lineBuffer.begin() + lineBufferOffset;
}
if (integerBufferOffset < integerBuffer.size())
{
integerBufferPosition = integerBuffer.begin() + integerBufferOffset;
}
if (lineBufferPosition == lineBuffer.cend())
{
lineBuffer.insert(lineBufferPosition, lineData);
}
else
{
std::copy(lineData.begin(), lineData.end(), lineBufferPosition);
}
if (integerBufferPosition == integerBuffer.cend())
{
integerBuffer.insert(integerBufferPosition, integerData);
}
else
{
std::copy(integerData.begin(), integerData.end(), integerBufferPosition);
}
auto hoverIt = std::find_if(hoverLines.begin(),
hoverLines.end(),
[&di](auto& entry) { return entry.di_ == di; });
if (di->visible_ && !di->hoverText_.empty())
{ {
const units::angle::radians<double> radians = angle; const units::angle::radians<double> radians = angle;
@ -486,13 +625,31 @@ void GeoLines::Impl::BufferLine(
const glm::vec2 obl = rotate * glm::vec2 {-hw, -hw}; const glm::vec2 obl = rotate * glm::vec2 {-hw, -hw};
const glm::vec2 obr = rotate * glm::vec2 {+hw, -hw}; const glm::vec2 obr = rotate * glm::vec2 {+hw, -hw};
newHoverLines_.emplace_back( if (hoverIt == hoverLines.end())
{
hoverLines.emplace_back(
LineHoverEntry {di, sc1, sc2, otl, otr, obl, obr}); LineHoverEntry {di, sc1, sc2, otl, otr, obl, obr});
} }
else
{
hoverIt->p1_ = sc1;
hoverIt->p2_ = sc2;
hoverIt->otl_ = otl;
hoverIt->otr_ = otr;
hoverIt->obl_ = obl;
hoverIt->obr_ = obr;
}
}
else if (hoverIt != hoverLines.end())
{
hoverLines.erase(hoverIt);
}
} }
void GeoLines::Impl::Update() void GeoLines::Impl::Update()
{ {
UpdateModifiedLineBuffers();
// If the lines have been updated // If the lines have been updated
if (dirty_) if (dirty_)
{ {

View file

@ -75,7 +75,7 @@ public:
* @param [in] longitude2 The longitude of the second endpoint of the geo * @param [in] longitude2 The longitude of the second endpoint of the geo
* line in degrees. * line in degrees.
*/ */
static void SetLineLocation(const std::shared_ptr<GeoLineDrawItem>& di, void SetLineLocation(const std::shared_ptr<GeoLineDrawItem>& di,
float latitude1, float latitude1,
float longitude1, float longitude1,
float latitude2, float latitude2,
@ -87,7 +87,7 @@ public:
* @param [in] di Geo line draw item * @param [in] di Geo line draw item
* @param [in] modulate Modulate color * @param [in] modulate Modulate color
*/ */
static void SetLineModulate(const std::shared_ptr<GeoLineDrawItem>& di, void SetLineModulate(const std::shared_ptr<GeoLineDrawItem>& di,
boost::gil::rgba8_pixel_t color); boost::gil::rgba8_pixel_t color);
/** /**
@ -96,7 +96,7 @@ public:
* @param [in] di Geo line draw item * @param [in] di Geo line draw item
* @param [in] modulate Modulate color * @param [in] modulate Modulate color
*/ */
static void SetLineModulate(const std::shared_ptr<GeoLineDrawItem>& di, void SetLineModulate(const std::shared_ptr<GeoLineDrawItem>& di,
boost::gil::rgba32f_pixel_t modulate); boost::gil::rgba32f_pixel_t modulate);
/** /**
@ -104,15 +104,14 @@ public:
* *
* @param [in] width Width in pixels * @param [in] width Width in pixels
*/ */
static void SetLineWidth(const std::shared_ptr<GeoLineDrawItem>& di, void SetLineWidth(const std::shared_ptr<GeoLineDrawItem>& di, float width);
float width);
/** /**
* Sets the visibility of the geo line. * Sets the visibility of the geo line.
* *
* @param [in] visible * @param [in] visible
*/ */
static void SetLineVisible(const std::shared_ptr<GeoLineDrawItem>& di, void SetLineVisible(const std::shared_ptr<GeoLineDrawItem>& di,
bool visible); bool visible);
/** /**
@ -121,9 +120,27 @@ public:
* @param [in] di Geo line draw item * @param [in] di Geo line draw item
* @param [in] text Hover text * @param [in] text Hover text
*/ */
static void SetLineHoverText(const std::shared_ptr<GeoLineDrawItem>& di, void SetLineHoverText(const std::shared_ptr<GeoLineDrawItem>& di,
const std::string& text); const std::string& text);
/**
* Sets the start time of a geo line.
*
* @param [in] di Geo line draw item
* @param [in] startTime Start time
*/
void SetLineStartTime(const std::shared_ptr<GeoLineDrawItem>& di,
std::chrono::system_clock::time_point startTime);
/**
* Sets the end time of a geo line.
*
* @param [in] di Geo line draw item
* @param [in] endTime End time
*/
void SetLineEndTime(const std::shared_ptr<GeoLineDrawItem>& di,
std::chrono::system_clock::time_point endTime);
/** /**
* Finalizes the draw item after adding new lines. * Finalizes the draw item after adding new lines.
*/ */

View file

@ -219,13 +219,13 @@ void LinkedVectors::FinishVectors()
const double& latitude2 = coordinate2.latitude_; const double& latitude2 = coordinate2.latitude_;
const double& longitude2 = coordinate2.longitude_; const double& longitude2 = coordinate2.longitude_;
GeoLines::SetLineLocation( p->geoLines_->SetLineLocation(
borderLine, latitude1, longitude1, latitude2, longitude2); borderLine, latitude1, longitude1, latitude2, longitude2);
GeoLines::SetLineModulate(borderLine, kBlack); p->geoLines_->SetLineModulate(borderLine, kBlack);
GeoLines::SetLineWidth(borderLine, di->width_ + 2.0f); p->geoLines_->SetLineWidth(borderLine, di->width_ + 2.0f);
GeoLines::SetLineVisible(borderLine, di->visible_); p->geoLines_->SetLineVisible(borderLine, di->visible_);
GeoLines::SetLineHoverText(borderLine, di->hoverText_); p->geoLines_->SetLineHoverText(borderLine, di->hoverText_);
di->borderDrawItems_.emplace_back(std::move(borderLine)); di->borderDrawItems_.emplace_back(std::move(borderLine));
@ -248,13 +248,13 @@ void LinkedVectors::FinishVectors()
auto tickBorderLine = p->geoLines_->AddLine(); auto tickBorderLine = p->geoLines_->AddLine();
GeoLines::SetLineLocation( p->geoLines_->SetLineLocation(
tickBorderLine, tickLat1, tickLon1, tickLat2, tickLon2); tickBorderLine, tickLat1, tickLon1, tickLat2, tickLon2);
GeoLines::SetLineModulate(tickBorderLine, kBlack); p->geoLines_->SetLineModulate(tickBorderLine, kBlack);
GeoLines::SetLineWidth(tickBorderLine, di->width_ + 2.0f); p->geoLines_->SetLineWidth(tickBorderLine, di->width_ + 2.0f);
GeoLines::SetLineVisible(tickBorderLine, di->visible_); p->geoLines_->SetLineVisible(tickBorderLine, di->visible_);
GeoLines::SetLineHoverText(tickBorderLine, di->hoverText_); p->geoLines_->SetLineHoverText(tickBorderLine, di->hoverText_);
tickRadius += di->tickRadiusIncrement_; tickRadius += di->tickRadiusIncrement_;
} }
@ -279,17 +279,17 @@ void LinkedVectors::FinishVectors()
const double& latitude2 = coordinate2.latitude_; const double& latitude2 = coordinate2.latitude_;
const double& longitude2 = coordinate2.longitude_; const double& longitude2 = coordinate2.longitude_;
GeoLines::SetLineLocation( p->geoLines_->SetLineLocation(
geoLine, latitude1, longitude1, latitude2, longitude2); geoLine, latitude1, longitude1, latitude2, longitude2);
GeoLines::SetLineModulate(geoLine, di->modulate_); p->geoLines_->SetLineModulate(geoLine, di->modulate_);
GeoLines::SetLineWidth(geoLine, di->width_); p->geoLines_->SetLineWidth(geoLine, di->width_);
GeoLines::SetLineVisible(geoLine, di->visible_); p->geoLines_->SetLineVisible(geoLine, di->visible_);
// If the border is not enabled, this line must have hover text instead // If the border is not enabled, this line must have hover text instead
if (!p->borderEnabled_) if (!p->borderEnabled_)
{ {
GeoLines::SetLineHoverText(geoLine, di->hoverText_); p->geoLines_->SetLineHoverText(geoLine, di->hoverText_);
} }
di->lineDrawItems_.emplace_back(std::move(geoLine)); di->lineDrawItems_.emplace_back(std::move(geoLine));
@ -313,17 +313,17 @@ void LinkedVectors::FinishVectors()
auto tickGeoLine = p->geoLines_->AddLine(); auto tickGeoLine = p->geoLines_->AddLine();
GeoLines::SetLineLocation( p->geoLines_->SetLineLocation(
tickGeoLine, tickLat1, tickLon1, tickLat2, tickLon2); tickGeoLine, tickLat1, tickLon1, tickLat2, tickLon2);
GeoLines::SetLineModulate(tickGeoLine, di->modulate_); p->geoLines_->SetLineModulate(tickGeoLine, di->modulate_);
GeoLines::SetLineWidth(tickGeoLine, di->width_); p->geoLines_->SetLineWidth(tickGeoLine, di->width_);
GeoLines::SetLineVisible(tickGeoLine, di->visible_); p->geoLines_->SetLineVisible(tickGeoLine, di->visible_);
// If the border is not enabled, this line must have hover text // If the border is not enabled, this line must have hover text
if (!p->borderEnabled_) if (!p->borderEnabled_)
{ {
GeoLines::SetLineHoverText(tickGeoLine, di->hoverText_); p->geoLines_->SetLineHoverText(tickGeoLine, di->hoverText_);
} }
tickRadius += di->tickRadiusIncrement_; tickRadius += di->tickRadiusIncrement_;