diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-04-11 03:06:48 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-04-11 04:50:04 +0200 |
commit | 18a8e3cc02f3f04ed644f57046ad95cc3e7b2db0 (patch) | |
tree | 3c069636a1a89dd8ad12a64bbdfc06adcc070fde | |
parent | b4ca16e3393138322f0a746db4406314386cde50 (diff) |
fix sprite bitmask generator
This is WIP because it needs a more efficient algorithm.
-rw-r--r-- | src/anim-atlas.cpp | 63 | ||||
-rw-r--r-- | test/bitmask.cpp | 14 | ||||
-rw-r--r-- | test/bitmask.embed.inc | 18 |
3 files changed, 42 insertions, 53 deletions
diff --git a/src/anim-atlas.cpp b/src/anim-atlas.cpp index 650ca41e..3386de06 100644 --- a/src/anim-atlas.cpp +++ b/src/anim-atlas.cpp @@ -16,6 +16,29 @@ static constexpr inline auto rot_count = size_t(rotation_COUNT); static_assert(std::size(name_array) == rot_count); static_assert(rot_count == 8); +namespace { + +constexpr uint8_t amin = 32; + +CORRADE_ALWAYS_INLINE void make_bitmask_impl(const ImageView2D& tex, BitArray& array) +{ + array.resetAll(); // slow + const auto pixels = tex.pixels(); + fm_soft_assert(tex.pixelSize() == 4); + fm_soft_assert(pixels.stride()[1] == 4); + + const auto* const src = (const unsigned char*)pixels.data(); + const auto stride = (size_t)pixels.stride()[0]; + const auto size = pixels.size(); + const auto width = size[1], height = size[0]; + + for (auto j = 0u; j < height; j++) + for (auto i = 0u; i < width; i++) + array.set((height - j - 1)*width + i, src[(j*stride + i*4)+3] >= amin); +} + +} // namespace + uint8_t anim_atlas::rotation_to_index(StringView name) { for (uint8_t i = 0; i < rot_count; i++) @@ -135,45 +158,7 @@ auto anim_atlas::frame_quad(const Vector3& center, rotation r, size_t i) const n void anim_atlas::make_bitmask_(const ImageView2D& tex, BitArray& array) { - // todo! decompose into a C function that can use __restrict - const auto pixels = tex.pixels(); - const auto size = pixels.size(); - const auto width = size[1], height = size[0], - stride = (size_t)pixels.stride()[0], width0 = width & ~7u; - const auto* const data = (const unsigned char*)pixels.data(); - auto* const dest = (unsigned char*)array.data(); - - fm_soft_assert(tex.pixelSize() == 4); - fm_soft_assert(pixels.stride()[1] == 4); - - for (auto j = 0uz; j < height; j++) - { - constexpr unsigned char amin = 32; - auto i = 0uz; - for (; i < width0; i += 8) - { - const auto src_idx = (j*stride + i*4)+3, dst_idx = (height-j-1)*width+i >> 3; - const unsigned char* buf = data + src_idx; - auto value = (unsigned char)( - (unsigned char)(buf[0*4] >= amin) << 0 | - (unsigned char)(buf[1*4] >= amin) << 1 | - (unsigned char)(buf[2*4] >= amin) << 2 | - (unsigned char)(buf[3*4] >= amin) << 3 | - (unsigned char)(buf[4*4] >= amin) << 4 | - (unsigned char)(buf[5*4] >= amin) << 5 | - (unsigned char)(buf[6*4] >= amin) << 6 | - (unsigned char)(buf[7*4] >= amin) << 7); - dest[dst_idx] = value; - } - if (i < width) - { - dest[(height-j-1)*width+i >> 3] = 0; - do { - unsigned char alpha = data[(j*stride + i*4)+3]; - array.set((height-j-1)*width + i, alpha >= amin); - } while (++i < width); - } - } + return make_bitmask_impl(tex, array); } BitArray anim_atlas::make_bitmask(const ImageView2D& tex) diff --git a/test/bitmask.cpp b/test/bitmask.cpp index f6abea14..d0b6c4d8 100644 --- a/test/bitmask.cpp +++ b/test/bitmask.cpp @@ -3,7 +3,6 @@ #include "src/anim-atlas.hpp" #include "loader/loader.hpp" #include <Corrade/Containers/ArrayView.h> -#include <Corrade/Containers/StridedArrayView.h> #include <mg/Functions.h> #include <mg/ImageData.h> @@ -16,12 +15,12 @@ const unsigned char src[] = { }; constexpr auto data_nbytes = arraySize(src); -constexpr auto size = Vector2i{8, 16}; -static_assert(size_t{size.product()+7}/8 <= data_nbytes); +constexpr auto size = Vector2i{21, 52}; +//static_assert(size_t{size.product()+7}/8 <= data_nbytes); void bitmask_test() { - auto img = loader.texture(loader.SCENERY_PATH, "door-close"_s); + auto img = loader.texture(loader.SCENERY_PATH, "control-panel"_s); auto bitmask = anim_atlas::make_bitmask(img); fm_assert(bitmask.size() >= size_t{size.product()}); fm_assert(img.pixelSize() == 4); @@ -40,8 +39,11 @@ void bitmask_test() const auto len = Math::min(data_nbytes, (size_t)bitmask.size()+7 >> 3); fm_assert(arraySize(src) >= len); for (auto i = 0uz; i < len; i++) - if ((unsigned char)bitmask.data()[i] != src[i]) - fm_abort("wrong value at byte %zu, should be' 0x%02hhx'", i, src[i]); + { + auto a = (unsigned char)bitmask.data()[i]; + if (a != src[i]) + fm_abort("wrong value 0x%02hhx at byte %zu, should be' 0x%02hhx'", a, i, src[i]); + } } } // namespace diff --git a/test/bitmask.embed.inc b/test/bitmask.embed.inc index 1dcc633e..2b1f7a5f 100644 --- a/test/bitmask.embed.inc +++ b/test/bitmask.embed.inc @@ -1,8 +1,10 @@ -0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0x03,0x00,0xe0,0x01,0x00,0x7c,0x00,0x80,0x3f,0x00,0xf0,0x1f,0x00,0xfe,0x0f, +0xc0,0xff,0x03,0xf8,0xff,0x01,0xff,0xff,0xe0,0xff,0x3f,0xfc,0xff,0x9f,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xfe,0xff,0x1f,0xff,0xff,0x83,0xff,0x7f,0xe0,0xff,0x0f,0xf0,0xff,0x01,0xf8, +0x3f,0x00,0xfe,0x07,0x00,0xff,0x00,0x80,0x1f,0x00,0xc0,0x03,0x00,0x70,0x00, +0x00,0xb8, |