Populate cached images into the texture atlas

This commit is contained in:
Dan Paulat 2023-07-30 22:31:05 -05:00
parent 0f9fbdbf63
commit 4c093d65f6
5 changed files with 104 additions and 18 deletions

View file

@ -27,6 +27,8 @@ static constexpr size_t kPointsPerVertex = 10;
static constexpr size_t kBufferLength =
kNumTriangles * kVerticesPerTriangle * kPointsPerVertex;
static const std::string kTextureName = "lines/default-1x7";
class GeoLine::Impl
{
public:
@ -115,7 +117,7 @@ void GeoLine::Initialize()
}
p->texture_ =
util::TextureAtlas::Instance().GetTextureAttributes("lines/default-1x7");
util::TextureAtlas::Instance().GetTextureAttributes(kTextureName);
gl.glGenVertexArrays(1, &p->vao_);
gl.glGenBuffers(1, &p->vbo_);
@ -248,6 +250,9 @@ void GeoLine::Impl::Update()
{
gl::OpenGLFunctions& gl = context_->gl();
texture_ =
util::TextureAtlas::Instance().GetTextureAttributes(kTextureName);
// Latitude and longitude coordinates in degrees
const float lx = points_[0].latitude_;
const float rx = points_[1].latitude_;

View file

@ -459,14 +459,23 @@ void PlacefileManager::Impl::LoadResources(
const QUrl baseUrl =
QUrl::fromUserInput(QString::fromStdString(placefile->name()));
// TODO: Parallelize
for (auto& iconFile : iconFiles)
{
QUrl fileUrl = QUrl(QString::fromStdString(iconFile->filename_));
QUrl resolvedUrl = baseUrl.resolved(fileUrl);
std::vector<std::string> urlStrings;
urlStrings.reserve(iconFiles.size());
ResourceManager::LoadImageResource(resolvedUrl.toString().toStdString());
}
std::transform(iconFiles.cbegin(),
iconFiles.cend(),
std::back_inserter(urlStrings),
[&baseUrl](auto& iconFile)
{
// Resolve target URL relative to base URL
QUrl fileUrl =
QUrl(QString::fromStdString(iconFile->filename_));
QUrl resolvedUrl = baseUrl.resolved(fileUrl);
return resolvedUrl.toString().toStdString();
});
ResourceManager::LoadImageResources(urlStrings);
}
} // namespace manager

View file

@ -5,6 +5,9 @@
#include <scwx/qt/util/texture_atlas.hpp>
#include <scwx/util/logger.hpp>
#include <execution>
#include <mutex>
#include <QFontDatabase>
#include <imgui.h>
@ -61,10 +64,36 @@ std::shared_ptr<util::Font> Font(types::Font font)
return nullptr;
}
void LoadImageResource(const std::string& urlString)
bool LoadImageResource(const std::string& urlString)
{
util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance();
textureAtlas.CacheTexture(urlString, urlString);
return textureAtlas.CacheTexture(urlString, urlString);
}
void LoadImageResources(const std::vector<std::string>& urlStrings)
{
std::mutex m {};
bool textureCached = false;
std::for_each(std::execution::par_unseq,
urlStrings.begin(),
urlStrings.end(),
[&](auto& urlString)
{
bool value = LoadImageResource(urlString);
if (value)
{
std::unique_lock lock {m};
textureCached = true;
}
});
if (textureCached)
{
util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance();
textureAtlas.BuildAtlas(1024, 1024);
}
}
static void LoadFonts()
@ -90,7 +119,7 @@ static void LoadTextures()
":/res/textures/lines/default-1x7.png");
textureAtlas.RegisterTexture("lines/test-pattern",
":/res/textures/lines/test-pattern.png");
textureAtlas.BuildAtlas(8, 8);
textureAtlas.BuildAtlas(1024, 1024);
}
} // namespace ResourceManager

View file

@ -18,7 +18,8 @@ void Shutdown();
int FontId(types::Font font);
std::shared_ptr<util::Font> Font(types::Font font);
void LoadImageResource(const std::string& urlString);
bool LoadImageResource(const std::string& urlString);
void LoadImageResources(const std::vector<std::string>& urlStrings);
} // namespace ResourceManager
} // namespace manager

View file

@ -5,6 +5,7 @@
#include <shared_mutex>
#include <unordered_map>
#include <variant>
#if defined(_MSC_VER)
# pragma warning(push, 0)
@ -111,8 +112,11 @@ void TextureAtlas::BuildAtlas(size_t width, size_t height)
return;
}
std::vector<std::pair<std::string, boost::gil::rgba8_image_t>> images;
std::vector<stbrp_rect> stbrpRects;
std::vector<std::pair<
std::string,
std::variant<boost::gil::rgba8_image_t, boost::gil::rgba8_image_t*>>>
images;
std::vector<stbrp_rect> stbrpRects;
// Load images
{
@ -145,9 +149,33 @@ void TextureAtlas::BuildAtlas(size_t width, size_t height)
});
}
// TODO: Cached images
{
// Cached images
// Take a read lock on the texture cache map. The read lock must persist
// through atlas population, as a pointer to the image is taken and used.
std::shared_lock textureCacheLock(p->textureCacheMutex_);
{
// For each cached texture
for (auto& texture : p->textureCache_)
{
auto& image = texture.second;
if (image.width() > 0u && image.height() > 0u)
{
// Store STB rectangle pack data in a vector
stbrpRects.push_back(
stbrp_rect {0,
static_cast<stbrp_coord>(image.width()),
static_cast<stbrp_coord>(image.height()),
0,
0,
0});
// Store image data in a vector
images.emplace_back(texture.first, &image);
}
}
}
// Pack images
@ -195,8 +223,22 @@ void TextureAtlas::BuildAtlas(size_t width, size_t height)
if (stbrpRects[i].was_packed != 0)
{
// Populate the atlas
boost::gil::rgba8c_view_t imageView =
boost::gil::const_view(images[i].second);
boost::gil::rgba8c_view_t imageView;
// Retrieve the image
if (std::holds_alternative<boost::gil::rgba8_image_t>(
images[i].second))
{
imageView = boost::gil::const_view(
std::get<boost::gil::rgba8_image_t>(images[i].second));
}
else if (std::holds_alternative<boost::gil::rgba8_image_t*>(
images[i].second))
{
imageView = boost::gil::const_view(
*std::get<boost::gil::rgba8_image_t*>(images[i].second));
}
boost::gil::rgba8_view_t atlasSubView =
boost::gil::subimage_view(atlasView,
stbrpRects[i].x,