Add texture atlas implementation
This commit is contained in:
parent
93fd269c02
commit
45b3369bc9
2 changed files with 156 additions and 0 deletions
75
libs/gfx/include/psemek/gfx/texture_atlas.hpp
Normal file
75
libs/gfx/include/psemek/gfx/texture_atlas.hpp
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/atlas.hpp>
|
||||||
|
#include <psemek/gfx/texture.hpp>
|
||||||
|
#include <psemek/gfx/texture_view.hpp>
|
||||||
|
|
||||||
|
namespace psemek::gfx
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Pixel, typename Key, typename Compare = std::less<Key>>
|
||||||
|
struct texture_atlas_2d
|
||||||
|
{
|
||||||
|
texture_atlas_2d(Pixel background = Pixel{}, Compare compare = Compare{});
|
||||||
|
|
||||||
|
using texture_view = texture_view_2d;
|
||||||
|
|
||||||
|
texture_2d & texture() { return texture_; }
|
||||||
|
texture_2d const & texture() const { return texture_; }
|
||||||
|
|
||||||
|
std::pair<texture_view, bool> insert(Key const & key, util::array<Pixel, 2> const & data);
|
||||||
|
texture_view find(Key const & key) const;
|
||||||
|
texture_view at(Key const & key) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
util::atlas<Pixel, 2, Key, Compare> atlas_;
|
||||||
|
texture_2d texture_;
|
||||||
|
|
||||||
|
void update_texture();
|
||||||
|
|
||||||
|
texture_view to_view(typename util::atlas<Pixel, 2, Key, Compare>::atlas_part const & part) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Pixel, typename Key, typename Compare>
|
||||||
|
texture_atlas_2d<Pixel, Key, Compare>::texture_atlas_2d(Pixel background, Compare compare)
|
||||||
|
: atlas_(std::move(background), std::move(compare))
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename Pixel, typename Key, typename Compare>
|
||||||
|
std::pair<texture_view_2d, bool> texture_atlas_2d<Pixel, Key, Compare>::insert(Key const & key, util::array<Pixel, 2> const & data)
|
||||||
|
{
|
||||||
|
auto result = atlas_.insert(key, data);
|
||||||
|
if (result.second)
|
||||||
|
update_texture();
|
||||||
|
|
||||||
|
return {to_view(result.first), result.second};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Pixel, typename Key, typename Compare>
|
||||||
|
texture_view_2d texture_atlas_2d<Pixel, Key, Compare>::find(Key const & key) const
|
||||||
|
{
|
||||||
|
auto result = atlas_.find(key);
|
||||||
|
if (result)
|
||||||
|
return to_view(*result);
|
||||||
|
return texture_view{};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Pixel, typename Key, typename Compare>
|
||||||
|
texture_view_2d texture_atlas_2d<Pixel, Key, Compare>::at(Key const & key) const
|
||||||
|
{
|
||||||
|
return to_view(atlas_.at(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Pixel, typename Key, typename Compare>
|
||||||
|
void texture_atlas_2d<Pixel, Key, Compare>::update_texture()
|
||||||
|
{
|
||||||
|
texture_.load(atlas_.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Pixel, typename Key, typename Compare>
|
||||||
|
texture_view_2d texture_atlas_2d<Pixel, Key, Compare>::to_view(typename util::atlas<Pixel, 2, Key, Compare>::atlas_part const & part) const
|
||||||
|
{
|
||||||
|
return texture_view{&texture_, {{{part.begin[0], part.end[0]}, {part.begin[1], part.end[1]}}}};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
81
libs/util/include/psemek/util/atlas.hpp
Normal file
81
libs/util/include/psemek/util/atlas.hpp
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/array.hpp>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace psemek::util
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T, std::size_t N, typename Key, typename Compare = std::less<Key>>
|
||||||
|
struct atlas;
|
||||||
|
|
||||||
|
template <typename T, typename Key, typename Compare>
|
||||||
|
struct atlas<T, 2, Key, Compare>
|
||||||
|
{
|
||||||
|
struct atlas_part
|
||||||
|
{
|
||||||
|
std::array<std::size_t, 2> begin;
|
||||||
|
std::array<std::size_t, 2> end;
|
||||||
|
};
|
||||||
|
|
||||||
|
atlas(T default_value = T{}, Compare compare = Compare{})
|
||||||
|
: default_value_(std::move(default_value))
|
||||||
|
, data_(std::move(compare))
|
||||||
|
{}
|
||||||
|
|
||||||
|
util::array<T, 2> const & array() const
|
||||||
|
{
|
||||||
|
return array_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<atlas_part, bool> insert(Key const & key, util::array<T, 2> const & data)
|
||||||
|
{
|
||||||
|
auto it = data_.find(key);
|
||||||
|
if (it != data_.end())
|
||||||
|
return {it->second, false};
|
||||||
|
|
||||||
|
atlas_part part;
|
||||||
|
part.begin[0] = array_.width();
|
||||||
|
part.end[0] = part.begin[0] + data.width();
|
||||||
|
part.begin[1] = 0;
|
||||||
|
part.end[1] = data.height();
|
||||||
|
|
||||||
|
std::size_t new_width = array_.width() + data.width();
|
||||||
|
std::size_t new_height = std::max(array_.height(), data.height());
|
||||||
|
|
||||||
|
array_.resize({new_width, new_height}, default_value_);
|
||||||
|
|
||||||
|
for (std::size_t y = 0; y < data.height(); ++y)
|
||||||
|
{
|
||||||
|
for (std::size_t x = 0; x < data.width(); ++x)
|
||||||
|
{
|
||||||
|
array_(part.begin[0] + x, part.begin[1] + y) = data(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data_[key] = part;
|
||||||
|
return {part, true};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<atlas_part> find(Key const & key) const
|
||||||
|
{
|
||||||
|
auto it = data_.find(key);
|
||||||
|
if (it != data_.end())
|
||||||
|
return it->second;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
atlas_part at(Key const & key) const
|
||||||
|
{
|
||||||
|
return data_.at(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T default_value_;
|
||||||
|
std::map<Key, atlas_part, Compare> data_;
|
||||||
|
util::array<T, 2> array_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue