mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 13:30:06 +00:00
For placefile icons, only buffer texture data on texture atlas update
This commit is contained in:
parent
854d4a43db
commit
44030fdf87
2 changed files with 200 additions and 78 deletions
|
|
@ -25,9 +25,12 @@ static constexpr std::size_t kNumRectangles = 1;
|
|||
static constexpr std::size_t kNumTriangles = kNumRectangles * 2;
|
||||
static constexpr std::size_t kVerticesPerTriangle = 3;
|
||||
static constexpr std::size_t kVerticesPerRectangle = kVerticesPerTriangle * 2;
|
||||
static constexpr std::size_t kPointsPerVertex = 11;
|
||||
static constexpr std::size_t kBufferLength =
|
||||
static constexpr std::size_t kPointsPerVertex = 9;
|
||||
static constexpr std::size_t kPointsPerTexCoord = 2;
|
||||
static constexpr std::size_t kIconBufferLength =
|
||||
kNumTriangles * kVerticesPerTriangle * kPointsPerVertex;
|
||||
static constexpr std::size_t kTextureBufferLength =
|
||||
kNumTriangles * kVerticesPerTriangle * kPointsPerTexCoord;
|
||||
|
||||
struct PlacefileIconInfo
|
||||
{
|
||||
|
|
@ -84,6 +87,7 @@ public:
|
|||
~Impl() {}
|
||||
|
||||
void UpdateBuffers();
|
||||
void UpdateTextureBuffer();
|
||||
void Update(bool textureAtlasChanged);
|
||||
|
||||
std::shared_ptr<GlContext> context_;
|
||||
|
|
@ -101,11 +105,18 @@ public:
|
|||
currentIconList_ {};
|
||||
std::vector<std::shared_ptr<const gr::Placefile::IconDrawItem>>
|
||||
newIconList_ {};
|
||||
std::vector<std::shared_ptr<const gr::Placefile::IconDrawItem>>
|
||||
newValidIconList_ {};
|
||||
|
||||
std::vector<IconHoverEntry> hoverIcons_ {};
|
||||
std::vector<float> currentIconBuffer_ {};
|
||||
std::vector<GLint> currentThresholdBuffer_ {};
|
||||
std::vector<float> newIconBuffer_ {};
|
||||
std::vector<GLint> newThresholdBuffer_ {};
|
||||
|
||||
std::vector<float> iconBuffer_ {};
|
||||
std::vector<GLint> thresholdBuffer_ {};
|
||||
std::vector<float> textureBuffer_ {};
|
||||
|
||||
std::vector<IconHoverEntry> currentHoverIcons_ {};
|
||||
std::vector<IconHoverEntry> newHoverIcons_ {};
|
||||
|
||||
std::shared_ptr<ShaderProgram> shaderProgram_;
|
||||
GLint uMVPMatrixLocation_;
|
||||
|
|
@ -114,7 +125,7 @@ public:
|
|||
GLint uMapDistanceLocation_;
|
||||
|
||||
GLuint vao_;
|
||||
std::array<GLuint, 2> vbo_;
|
||||
std::array<GLuint, 3> vbo_;
|
||||
|
||||
GLsizei numVertices_;
|
||||
};
|
||||
|
|
@ -150,7 +161,7 @@ void PlacefileIcons::Initialize()
|
|||
p->shaderProgram_->GetUniformLocation("uMapDistance");
|
||||
|
||||
gl.glGenVertexArrays(1, &p->vao_);
|
||||
gl.glGenBuffers(2, p->vbo_.data());
|
||||
gl.glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data());
|
||||
|
||||
gl.glBindVertexArray(p->vao_);
|
||||
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]);
|
||||
|
|
@ -174,22 +185,13 @@ void PlacefileIcons::Initialize()
|
|||
reinterpret_cast<void*>(2 * sizeof(float)));
|
||||
gl.glEnableVertexAttribArray(1);
|
||||
|
||||
// aTexCoord
|
||||
gl.glVertexAttribPointer(2,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
kPointsPerVertex * sizeof(float),
|
||||
reinterpret_cast<void*>(4 * sizeof(float)));
|
||||
gl.glEnableVertexAttribArray(2);
|
||||
|
||||
// aModulate
|
||||
gl.glVertexAttribPointer(3,
|
||||
4,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
kPointsPerVertex * sizeof(float),
|
||||
reinterpret_cast<void*>(6 * sizeof(float)));
|
||||
reinterpret_cast<void*>(4 * sizeof(float)));
|
||||
gl.glEnableVertexAttribArray(3);
|
||||
|
||||
// aAngle
|
||||
|
|
@ -198,12 +200,24 @@ void PlacefileIcons::Initialize()
|
|||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
kPointsPerVertex * sizeof(float),
|
||||
reinterpret_cast<void*>(10 * sizeof(float)));
|
||||
reinterpret_cast<void*>(8 * sizeof(float)));
|
||||
gl.glEnableVertexAttribArray(4);
|
||||
|
||||
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]);
|
||||
gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW);
|
||||
|
||||
// aTexCoord
|
||||
gl.glVertexAttribPointer(2,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
kPointsPerTexCoord * sizeof(float),
|
||||
static_cast<void*>(0));
|
||||
gl.glEnableVertexAttribArray(2);
|
||||
|
||||
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]);
|
||||
gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW);
|
||||
|
||||
// aThreshold
|
||||
gl.glVertexAttribIPointer(5, //
|
||||
1,
|
||||
|
|
@ -260,15 +274,16 @@ void PlacefileIcons::Deinitialize()
|
|||
gl::OpenGLFunctions& gl = p->context_->gl();
|
||||
|
||||
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->iconMutex_};
|
||||
|
||||
p->currentIconList_.clear();
|
||||
p->currentIconFiles_.clear();
|
||||
p->hoverIcons_.clear();
|
||||
p->iconBuffer_.clear();
|
||||
p->thresholdBuffer_.clear();
|
||||
p->currentHoverIcons_.clear();
|
||||
p->currentIconBuffer_.clear();
|
||||
p->currentThresholdBuffer_.clear();
|
||||
p->textureBuffer_.clear();
|
||||
}
|
||||
|
||||
void PlacefileIconInfo::UpdateTextureInfo()
|
||||
|
|
@ -306,7 +321,11 @@ void PlacefileIcons::StartIcons()
|
|||
{
|
||||
// Clear the new buffer
|
||||
p->newIconList_.clear();
|
||||
p->newValidIconList_.clear();
|
||||
p->newIconFiles_.clear();
|
||||
p->newIconBuffer_.clear();
|
||||
p->newThresholdBuffer_.clear();
|
||||
p->newHoverIcons_.clear();
|
||||
}
|
||||
|
||||
void PlacefileIcons::SetIconFiles(
|
||||
|
|
@ -334,15 +353,31 @@ void PlacefileIcons::AddIcon(
|
|||
|
||||
void PlacefileIcons::FinishIcons()
|
||||
{
|
||||
// Update icon files
|
||||
for (auto& iconFile : p->newIconFiles_)
|
||||
{
|
||||
iconFile.second.UpdateTextureInfo();
|
||||
}
|
||||
|
||||
// Update buffers
|
||||
p->UpdateBuffers();
|
||||
|
||||
std::unique_lock lock {p->iconMutex_};
|
||||
|
||||
// Swap buffers
|
||||
p->currentIconList_.swap(p->newIconList_);
|
||||
p->currentIconList_.swap(p->newValidIconList_);
|
||||
p->currentIconFiles_.swap(p->newIconFiles_);
|
||||
p->currentIconBuffer_.swap(p->newIconBuffer_);
|
||||
p->currentThresholdBuffer_.swap(p->newThresholdBuffer_);
|
||||
p->currentHoverIcons_.swap(p->newHoverIcons_);
|
||||
|
||||
// Clear the new buffers
|
||||
p->newIconList_.clear();
|
||||
p->newValidIconList_.clear();
|
||||
p->newIconFiles_.clear();
|
||||
p->newIconBuffer_.clear();
|
||||
p->newThresholdBuffer_.clear();
|
||||
p->newHoverIcons_.clear();
|
||||
|
||||
// Mark the draw item dirty
|
||||
p->dirty_ = true;
|
||||
|
|
@ -350,17 +385,15 @@ void PlacefileIcons::FinishIcons()
|
|||
|
||||
void PlacefileIcons::Impl::UpdateBuffers()
|
||||
{
|
||||
iconBuffer_.clear();
|
||||
iconBuffer_.reserve(currentIconList_.size() * kBufferLength);
|
||||
thresholdBuffer_.clear();
|
||||
thresholdBuffer_.reserve(currentIconList_.size() * kVerticesPerRectangle);
|
||||
hoverIcons_.clear();
|
||||
numVertices_ = 0;
|
||||
newIconBuffer_.clear();
|
||||
newIconBuffer_.reserve(newIconList_.size() * kIconBufferLength);
|
||||
newThresholdBuffer_.clear();
|
||||
newThresholdBuffer_.reserve(newIconList_.size() * kVerticesPerRectangle);
|
||||
|
||||
for (auto& di : currentIconList_)
|
||||
for (auto& di : newIconList_)
|
||||
{
|
||||
auto it = currentIconFiles_.find(di->fileNumber_);
|
||||
if (it == currentIconFiles_.cend())
|
||||
auto it = newIconFiles_.find(di->fileNumber_);
|
||||
if (it == newIconFiles_.cend())
|
||||
{
|
||||
// No file found
|
||||
logger_->trace("Could not find file number: {}", di->fileNumber_);
|
||||
|
|
@ -377,6 +410,9 @@ void PlacefileIcons::Impl::UpdateBuffers()
|
|||
continue;
|
||||
}
|
||||
|
||||
// Icon is valid, add to valid icon list
|
||||
newValidIconList_.push_back(di);
|
||||
|
||||
// Threshold value
|
||||
units::length::nautical_miles<double> threshold = di->threshold_;
|
||||
GLint thresholdValue = static_cast<GLint>(std::round(threshold.value()));
|
||||
|
|
@ -407,42 +443,29 @@ void PlacefileIcons::Impl::UpdateBuffers()
|
|||
units::angle::degrees<float> angle = di->angle_;
|
||||
const float a = angle.value();
|
||||
|
||||
// Texture coordinates
|
||||
const std::size_t iconRow = (di->iconNumber_ - 1) / icon.columns_;
|
||||
const std::size_t iconColumn = (di->iconNumber_ - 1) % icon.columns_;
|
||||
|
||||
const float iconX = iconColumn * icon.scaledWidth_;
|
||||
const float iconY = iconRow * icon.scaledHeight_;
|
||||
|
||||
const float ls = icon.texture_.sLeft_ + iconX;
|
||||
const float rs = ls + icon.scaledWidth_;
|
||||
const float tt = icon.texture_.tTop_ + iconY;
|
||||
const float bt = tt + icon.scaledHeight_;
|
||||
|
||||
// Fixed modulate color
|
||||
const float mc0 = 1.0f;
|
||||
const float mc1 = 1.0f;
|
||||
const float mc2 = 1.0f;
|
||||
const float mc3 = 1.0f;
|
||||
|
||||
iconBuffer_.insert(
|
||||
iconBuffer_.end(),
|
||||
{
|
||||
// Icon
|
||||
lat, lon, lx, by, ls, bt, mc0, mc1, mc2, mc3, a, // BL
|
||||
lat, lon, lx, ty, ls, tt, mc0, mc1, mc2, mc3, a, // TL
|
||||
lat, lon, rx, by, rs, bt, mc0, mc1, mc2, mc3, a, // BR
|
||||
lat, lon, rx, by, rs, bt, mc0, mc1, mc2, mc3, a, // BR
|
||||
lat, lon, rx, ty, rs, tt, mc0, mc1, mc2, mc3, a, // TR
|
||||
lat, lon, lx, ty, ls, tt, mc0, mc1, mc2, mc3, a // TL
|
||||
});
|
||||
thresholdBuffer_.insert(thresholdBuffer_.end(),
|
||||
{thresholdValue, //
|
||||
thresholdValue,
|
||||
thresholdValue,
|
||||
thresholdValue,
|
||||
thresholdValue,
|
||||
thresholdValue});
|
||||
newIconBuffer_.insert(newIconBuffer_.end(),
|
||||
{
|
||||
// Icon
|
||||
lat, lon, lx, by, mc0, mc1, mc2, mc3, a, // BL
|
||||
lat, lon, lx, ty, mc0, mc1, mc2, mc3, a, // TL
|
||||
lat, lon, rx, by, mc0, mc1, mc2, mc3, a, // BR
|
||||
lat, lon, rx, by, mc0, mc1, mc2, mc3, a, // BR
|
||||
lat, lon, rx, ty, mc0, mc1, mc2, mc3, a, // TR
|
||||
lat, lon, lx, ty, mc0, mc1, mc2, mc3, a // TL
|
||||
});
|
||||
newThresholdBuffer_.insert(newThresholdBuffer_.end(),
|
||||
{thresholdValue, //
|
||||
thresholdValue,
|
||||
thresholdValue,
|
||||
thresholdValue,
|
||||
thresholdValue,
|
||||
thresholdValue});
|
||||
|
||||
if (!di->hoverText_.empty())
|
||||
{
|
||||
|
|
@ -460,15 +483,105 @@ void PlacefileIcons::Impl::UpdateBuffers()
|
|||
const glm::vec2 obl = rotate * glm::vec2 {lx, by};
|
||||
const glm::vec2 obr = rotate * glm::vec2 {rx, by};
|
||||
|
||||
hoverIcons_.emplace_back(IconHoverEntry {di, sc, otl, otr, obl, obr});
|
||||
newHoverIcons_.emplace_back(
|
||||
IconHoverEntry {di, sc, otl, otr, obl, obr});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dirty_ = true;
|
||||
void PlacefileIcons::Impl::UpdateTextureBuffer()
|
||||
{
|
||||
textureBuffer_.clear();
|
||||
textureBuffer_.reserve(currentIconList_.size() * kTextureBufferLength);
|
||||
|
||||
for (auto& di : currentIconList_)
|
||||
{
|
||||
auto it = currentIconFiles_.find(di->fileNumber_);
|
||||
if (it == currentIconFiles_.cend())
|
||||
{
|
||||
// No file found
|
||||
logger_->trace("Could not find file number: {}", di->fileNumber_);
|
||||
|
||||
// Should not get here, but insert empty data to match up with data
|
||||
// already buffered
|
||||
|
||||
// clang-format off
|
||||
textureBuffer_.insert(
|
||||
textureBuffer_.end(),
|
||||
{
|
||||
// Icon
|
||||
0.0f, 0.0f, // BL
|
||||
0.0f, 0.0f, // TL
|
||||
0.0f, 0.0f, // BR
|
||||
0.0f, 0.0f, // BR
|
||||
0.0f, 0.0f, // TR
|
||||
0.0f, 0.0f // TL
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& icon = it->second;
|
||||
|
||||
// Validate icon
|
||||
if (di->iconNumber_ == 0 || di->iconNumber_ > icon.numIcons_)
|
||||
{
|
||||
// No icon found
|
||||
logger_->trace("Invalid icon number: {}", di->iconNumber_);
|
||||
|
||||
// Will get here if a texture changes, and the texture shrunk such that
|
||||
// the icon is no longer found
|
||||
|
||||
// clang-format off
|
||||
textureBuffer_.insert(
|
||||
textureBuffer_.end(),
|
||||
{
|
||||
// Icon
|
||||
0.0f, 0.0f, // BL
|
||||
0.0f, 0.0f, // TL
|
||||
0.0f, 0.0f, // BR
|
||||
0.0f, 0.0f, // BR
|
||||
0.0f, 0.0f, // TR
|
||||
0.0f, 0.0f // TL
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Texture coordinates
|
||||
const std::size_t iconRow = (di->iconNumber_ - 1) / icon.columns_;
|
||||
const std::size_t iconColumn = (di->iconNumber_ - 1) % icon.columns_;
|
||||
|
||||
const float iconX = iconColumn * icon.scaledWidth_;
|
||||
const float iconY = iconRow * icon.scaledHeight_;
|
||||
|
||||
const float ls = icon.texture_.sLeft_ + iconX;
|
||||
const float rs = ls + icon.scaledWidth_;
|
||||
const float tt = icon.texture_.tTop_ + iconY;
|
||||
const float bt = tt + icon.scaledHeight_;
|
||||
|
||||
// clang-format off
|
||||
textureBuffer_.insert(
|
||||
textureBuffer_.end(),
|
||||
{
|
||||
// Icon
|
||||
ls, bt, // BL
|
||||
ls, tt, // TL
|
||||
rs, bt, // BR
|
||||
rs, bt, // BR
|
||||
rs, tt, // TR
|
||||
ls, tt // TL
|
||||
});
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
|
||||
void PlacefileIcons::Impl::Update(bool textureAtlasChanged)
|
||||
{
|
||||
gl::OpenGLFunctions& gl = context_->gl();
|
||||
|
||||
// If the texture atlas has changed
|
||||
if (dirty_ || textureAtlasChanged)
|
||||
{
|
||||
|
|
@ -478,27 +591,36 @@ void PlacefileIcons::Impl::Update(bool textureAtlasChanged)
|
|||
iconFile.second.UpdateTextureInfo();
|
||||
}
|
||||
|
||||
// Update OpenGL buffer data
|
||||
UpdateBuffers();
|
||||
// Update OpenGL texture buffer data
|
||||
UpdateTextureBuffer();
|
||||
|
||||
gl::OpenGLFunctions& gl = context_->gl();
|
||||
// Buffer texture data
|
||||
gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]);
|
||||
gl.glBufferData(GL_ARRAY_BUFFER,
|
||||
sizeof(float) * textureBuffer_.size(),
|
||||
textureBuffer_.data(),
|
||||
GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
// If buffers need updating
|
||||
if (dirty_)
|
||||
{
|
||||
// Buffer vertex data
|
||||
gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]);
|
||||
gl.glBufferData(GL_ARRAY_BUFFER,
|
||||
sizeof(float) * iconBuffer_.size(),
|
||||
iconBuffer_.data(),
|
||||
sizeof(float) * currentIconBuffer_.size(),
|
||||
currentIconBuffer_.data(),
|
||||
GL_DYNAMIC_DRAW);
|
||||
|
||||
// Buffer threshold data
|
||||
gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]);
|
||||
gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]);
|
||||
gl.glBufferData(GL_ARRAY_BUFFER,
|
||||
sizeof(GLint) * thresholdBuffer_.size(),
|
||||
thresholdBuffer_.data(),
|
||||
sizeof(GLint) * currentThresholdBuffer_.size(),
|
||||
currentThresholdBuffer_.data(),
|
||||
GL_DYNAMIC_DRAW);
|
||||
|
||||
numVertices_ =
|
||||
static_cast<GLsizei>(iconBuffer_.size() / kVerticesPerRectangle);
|
||||
numVertices_ = static_cast<GLsizei>(currentIconBuffer_.size() /
|
||||
kVerticesPerRectangle);
|
||||
}
|
||||
|
||||
dirty_ = false;
|
||||
|
|
@ -530,8 +652,8 @@ bool PlacefileIcons::RunMousePicking(
|
|||
// For each pickable icon
|
||||
auto it = std::find_if(
|
||||
std::execution::par_unseq,
|
||||
p->hoverIcons_.crbegin(),
|
||||
p->hoverIcons_.crend(),
|
||||
p->currentHoverIcons_.crbegin(),
|
||||
p->currentHoverIcons_.crend(),
|
||||
[&mapDistance, &mapMatrix, &mousePos](const auto& icon)
|
||||
{
|
||||
if (
|
||||
|
|
@ -574,7 +696,7 @@ bool PlacefileIcons::RunMousePicking(
|
|||
return util::maplibre::IsPointInPolygon({tl, bl, br, tr}, mousePos);
|
||||
});
|
||||
|
||||
if (it != p->hoverIcons_.crend())
|
||||
if (it != p->currentHoverIcons_.crend())
|
||||
{
|
||||
itemPicked = true;
|
||||
util::ImGui::Instance().DrawTooltip(it->di_->hoverText_);
|
||||
|
|
|
|||
|
|
@ -62,10 +62,10 @@ PlacefileLayer::PlacefileLayer(const std::shared_ptr<MapContext>& context,
|
|||
DrawLayer(context),
|
||||
p(std::make_unique<PlacefileLayer::Impl>(this, context, placefileName))
|
||||
{
|
||||
AddDrawItem(p->placefileIcons_);
|
||||
AddDrawItem(p->placefilePolygons_);
|
||||
AddDrawItem(p->placefileTriangles_);
|
||||
AddDrawItem(p->placefileLines_);
|
||||
AddDrawItem(p->placefileIcons_);
|
||||
AddDrawItem(p->placefileText_);
|
||||
|
||||
ReloadData();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue