Update placefile icon data outside of render loop, polygon and text cleanup

This commit is contained in:
Dan Paulat 2023-08-19 22:19:32 -05:00
parent b159540215
commit e021484bfb
5 changed files with 212 additions and 178 deletions

View file

@ -36,39 +36,16 @@ struct PlacefileIconInfo
// Resolve using base URL
auto baseUrl = QUrl::fromUserInput(QString::fromStdString(baseUrlString));
auto relativeUrl = QUrl(QString::fromStdString(iconFile->filename_));
resolvedUrl_ = baseUrl.resolved(relativeUrl).toString().toStdString();
texture_ = util::TextureAtlas::Instance().GetTextureAttributes(
baseUrl.resolved(relativeUrl).toString().toStdString());
if (iconFile->iconWidth_ > 0 && iconFile->iconHeight_ > 0)
{
columns_ = texture_.size_.x / iconFile->iconWidth_;
rows_ = texture_.size_.y / iconFile->iconHeight_;
}
else
{
columns_ = 0u;
rows_ = 0u;
UpdateTextureInfo();
}
numIcons_ = columns_ * rows_;
// Pixel size
float xFactor = 0.0f;
float yFactor = 0.0f;
if (texture_.size_.x > 0 && texture_.size_.y > 0)
{
xFactor = (texture_.sRight_ - texture_.sLeft_) / texture_.size_.x;
yFactor = (texture_.tBottom_ - texture_.tTop_) / texture_.size_.y;
}
scaledWidth_ = iconFile_->iconWidth_ * xFactor;
scaledHeight_ = iconFile_->iconHeight_ * yFactor;
}
void UpdateTextureInfo();
std::string resolvedUrl_;
std::shared_ptr<const gr::Placefile::IconFile> iconFile_;
util::TextureAttributes texture_;
util::TextureAttributes texture_ {};
std::size_t rows_ {};
std::size_t columns_ {};
std::size_t numIcons_ {};
@ -99,10 +76,20 @@ public:
bool dirty_ {false};
bool thresholded_ {false};
boost::unordered_flat_map<std::size_t, const PlacefileIconInfo>
iconFiles_ {};
std::mutex iconMutex_;
std::vector<std::shared_ptr<const gr::Placefile::IconDrawItem>> iconList_ {};
boost::unordered_flat_map<std::size_t, const PlacefileIconInfo>
currentIconFiles_ {};
boost::unordered_flat_map<std::size_t, const PlacefileIconInfo>
newIconFiles_ {};
std::vector<std::shared_ptr<const gr::Placefile::IconDrawItem>>
currentIconList_ {};
std::vector<std::shared_ptr<const gr::Placefile::IconDrawItem>>
newIconList_ {};
std::vector<float> iconBuffer_ {};
std::vector<GLint> thresholdBuffer_ {};
std::shared_ptr<ShaderProgram> shaderProgram_;
GLint uMVPMatrixLocation_;
@ -115,6 +102,7 @@ public:
GLsizei numVertices_;
void UpdateBuffers();
void Update();
};
@ -217,7 +205,9 @@ void PlacefileIcons::Initialize()
void PlacefileIcons::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
{
if (!p->iconList_.empty())
std::unique_lock lock {p->iconMutex_};
if (!p->currentIconList_.empty())
{
gl::OpenGLFunctions& gl = p->context_->gl();
@ -257,20 +247,61 @@ void PlacefileIcons::Deinitialize()
gl.glDeleteVertexArrays(1, &p->vao_);
gl.glDeleteBuffers(2, p->vbo_.data());
std::unique_lock lock {p->iconMutex_};
p->currentIconList_.clear();
p->currentIconFiles_.clear();
p->iconBuffer_.clear();
p->thresholdBuffer_.clear();
}
void PlacefileIconInfo::UpdateTextureInfo()
{
texture_ = util::TextureAtlas::Instance().GetTextureAttributes(resolvedUrl_);
if (iconFile_->iconWidth_ > 0 && iconFile_->iconHeight_ > 0)
{
columns_ = texture_.size_.x / iconFile_->iconWidth_;
rows_ = texture_.size_.y / iconFile_->iconHeight_;
}
else
{
columns_ = 0u;
rows_ = 0u;
}
numIcons_ = columns_ * rows_;
// Pixel size
float xFactor = 0.0f;
float yFactor = 0.0f;
if (texture_.size_.x > 0 && texture_.size_.y > 0)
{
xFactor = (texture_.sRight_ - texture_.sLeft_) / texture_.size_.x;
yFactor = (texture_.tBottom_ - texture_.tTop_) / texture_.size_.y;
}
scaledWidth_ = iconFile_->iconWidth_ * xFactor;
scaledHeight_ = iconFile_->iconHeight_ * yFactor;
}
void PlacefileIcons::StartIcons()
{
// Clear the new buffer
p->newIconList_.clear();
p->newIconFiles_.clear();
}
void PlacefileIcons::SetIconFiles(
const std::vector<std::shared_ptr<const gr::Placefile::IconFile>>& iconFiles,
const std::string& baseUrl)
{
p->dirty_ = true;
// Populate icon file map
p->iconFiles_.clear();
for (auto& file : iconFiles)
{
p->iconFiles_.emplace(
p->newIconFiles_.emplace(
std::piecewise_construct,
std::tuple {file->fileNumber_},
std::forward_as_tuple(PlacefileIconInfo {file, baseUrl}));
@ -282,34 +313,40 @@ void PlacefileIcons::AddIcon(
{
if (di != nullptr)
{
p->iconList_.emplace_back(di);
p->dirty_ = true;
p->newIconList_.emplace_back(di);
}
}
void PlacefileIcons::Reset()
void PlacefileIcons::FinishIcons()
{
// Clear the icon list, and mark the draw item dirty
p->iconList_.clear();
std::unique_lock lock {p->iconMutex_};
// Swap buffers
p->currentIconList_.swap(p->newIconList_);
p->currentIconFiles_.swap(p->newIconFiles_);
// Clear the new buffers
p->newIconList_.clear();
p->newIconFiles_.clear();
p->UpdateBuffers();
// Mark the draw item dirty
p->dirty_ = true;
}
void PlacefileIcons::Impl::Update()
void PlacefileIcons::Impl::UpdateBuffers()
{
if (dirty_)
{
static std::vector<float> buffer {};
static std::vector<GLint> thresholds {};
buffer.clear();
buffer.reserve(iconList_.size() * kBufferLength);
thresholds.clear();
thresholds.reserve(iconList_.size() * kVerticesPerRectangle);
iconBuffer_.clear();
iconBuffer_.reserve(currentIconList_.size() * kBufferLength);
thresholdBuffer_.clear();
thresholdBuffer_.reserve(currentIconList_.size() * kVerticesPerRectangle);
numVertices_ = 0;
for (auto& di : iconList_)
for (auto& di : currentIconList_)
{
auto it = iconFiles_.find(di->fileNumber_);
if (it == iconFiles_.cend())
auto it = currentIconFiles_.find(di->fileNumber_);
if (it == currentIconFiles_.cend())
{
// No file found
logger_->trace("Could not find file number: {}", di->fileNumber_);
@ -328,8 +365,7 @@ void PlacefileIcons::Impl::Update()
// Threshold value
units::length::nautical_miles<double> threshold = di->threshold_;
GLint thresholdValue =
static_cast<GLint>(std::round(threshold.value()));
GLint thresholdValue = static_cast<GLint>(std::round(threshold.value()));
// Latitude and longitude coordinates in degrees
const float lat = static_cast<float>(di->latitude_);
@ -375,7 +411,8 @@ void PlacefileIcons::Impl::Update()
const float mc2 = 1.0f;
const float mc3 = 1.0f;
buffer.insert(buffer.end(),
iconBuffer_.insert(
iconBuffer_.end(),
{
// Icon
lat, lon, lx, by, ls, bt, mc0, mc1, mc2, mc3, a, // BL
@ -385,35 +422,43 @@ void PlacefileIcons::Impl::Update()
lat, lon, rx, ty, rs, tt, mc0, mc1, mc2, mc3, a, // TR
lat, lon, lx, ty, ls, tt, mc0, mc1, mc2, mc3, a // TL
});
thresholds.insert(thresholds.end(),
thresholdBuffer_.insert(thresholdBuffer_.end(),
{thresholdValue, //
thresholdValue,
thresholdValue,
thresholdValue,
thresholdValue,
thresholdValue});
numVertices_ += 6;
}
dirty_ = true;
}
void PlacefileIcons::Impl::Update()
{
if (dirty_)
{
gl::OpenGLFunctions& gl = context_->gl();
// Buffer vertex data
gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]);
gl.glBufferData(GL_ARRAY_BUFFER,
sizeof(float) * buffer.size(),
buffer.data(),
sizeof(float) * iconBuffer_.size(),
iconBuffer_.data(),
GL_DYNAMIC_DRAW);
// Buffer threshold data
gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]);
gl.glBufferData(GL_ARRAY_BUFFER,
sizeof(GLint) * thresholds.size(),
thresholds.data(),
sizeof(GLint) * thresholdBuffer_.size(),
thresholdBuffer_.data(),
GL_DYNAMIC_DRAW);
dirty_ = false;
numVertices_ =
static_cast<GLsizei>(iconBuffer_.size() / kVerticesPerRectangle);
}
dirty_ = false;
}
} // namespace draw

View file

@ -33,6 +33,11 @@ public:
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override;
void Deinitialize() override;
/**
* Resets and prepares the draw item for adding a new set of icons.
*/
void StartIcons();
/**
* Configures the textures for drawing the placefile icons.
*
@ -52,9 +57,9 @@ public:
void AddIcon(const std::shared_ptr<gr::Placefile::IconDrawItem>& di);
/**
* Resets the list of icons in preparation for rendering a new frame.
* Finalizes the draw item after adding new icons.
*/
void Reset();
void FinishIcons();
private:
class Impl;

View file

@ -234,6 +234,8 @@ void PlacefilePolygons::Deinitialize()
gl.glDeleteVertexArrays(1, &p->vao_);
gl.glDeleteBuffers(2, p->vbo_.data());
std::unique_lock lock {p->bufferMutex_};
// Clear the current buffers
p->currentBuffer_.clear();
p->currentThresholdBuffer_.clear();

View file

@ -205,6 +205,8 @@ void PlacefileText::Impl::RenderText(
void PlacefileText::Deinitialize()
{
std::unique_lock lock {p->listMutex_};
// Clear the text list
p->textList_.clear();
}

View file

@ -44,7 +44,6 @@ public:
std::string placefileName_;
std::mutex dataMutex_ {};
bool dirty_ {true};
std::shared_ptr<gl::draw::PlacefileIcons> placefileIcons_;
std::shared_ptr<gl::draw::PlacefilePolygons> placefilePolygons_;
@ -89,9 +88,9 @@ std::string PlacefileLayer::placefile_name() const
void PlacefileLayer::set_placefile_name(const std::string& placefileName)
{
p->placefileName_ = placefileName;
p->dirty_ = true;
p->placefileText_->set_placefile_name(placefileName);
ReloadData();
}
void PlacefileLayer::Initialize()
@ -122,29 +121,6 @@ void PlacefileLayer::Render(
p->placefileIcons_->set_thresholded(thresholded);
p->placefilePolygons_->set_thresholded(thresholded);
p->placefileText_->set_thresholded(thresholded);
if (p->dirty_)
{
// Reset Placefile Icons
p->placefileIcons_->Reset();
p->placefileIcons_->SetIconFiles(placefile->icon_files(),
placefile->name());
for (auto& drawItem : placefile->GetDrawItems())
{
switch (drawItem->itemType_)
{
case gr::Placefile::ItemType::Icon:
p->placefileIcons_->AddIcon(
std::static_pointer_cast<gr::Placefile::IconDrawItem>(
drawItem));
break;
default:
break;
}
}
}
}
DrawLayer::Render(params);
@ -161,9 +137,6 @@ void PlacefileLayer::Deinitialize()
void PlacefileLayer::ReloadData()
{
// TODO: No longer needed after moving Icon Render items here
p->dirty_ = true;
boost::asio::post(
p->threadPool_,
[this]()
@ -182,9 +155,13 @@ void PlacefileLayer::ReloadData()
}
// Start draw items
p->placefileIcons_->StartIcons();
p->placefilePolygons_->StartPolygons();
p->placefileText_->StartText();
p->placefileIcons_->SetIconFiles(placefile->icon_files(),
placefile->name());
for (auto& drawItem : placefile->GetDrawItems())
{
switch (drawItem->itemType_)
@ -196,7 +173,9 @@ void PlacefileLayer::ReloadData()
break;
case gr::Placefile::ItemType::Icon:
// TODO
p->placefileIcons_->AddIcon(
std::static_pointer_cast<gr::Placefile::IconDrawItem>(
drawItem));
break;
case gr::Placefile::ItemType::Polygon:
@ -211,6 +190,7 @@ void PlacefileLayer::ReloadData()
}
// Finish draw items
p->placefileIcons_->FinishIcons();
p->placefilePolygons_->FinishPolygons();
p->placefileText_->FinishText();