diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | anim/serialize.cpp | 83 | ||||
-rw-r--r-- | anim/serialize.hpp | 2 | ||||
-rw-r--r-- | crop-tool/CMakeLists.txt | 2 | ||||
-rw-r--r-- | crop-tool/atlas.cpp (renamed from anim/atlas.cpp) | 2 | ||||
-rw-r--r-- | crop-tool/atlas.hpp (renamed from anim/atlas.hpp) | 0 | ||||
-rw-r--r-- | crop-tool/crop-tool.cpp | 2 | ||||
-rw-r--r-- | fake-json.hpp | 31 | ||||
-rw-r--r-- | json-magnum.hpp | 100 | ||||
-rw-r--r-- | loader-impl.cpp | 10 | ||||
-rw-r--r-- | loader.hpp | 4 | ||||
-rw-r--r-- | main.cpp | 10 | ||||
-rw-r--r-- | shaders/tile-shader.frag | 1 | ||||
-rw-r--r-- | tile-atlas.cpp (renamed from texture-atlas.cpp) | 20 | ||||
-rw-r--r-- | tile-atlas.hpp (renamed from texture-atlas.hpp) | 8 | ||||
-rw-r--r-- | tile-tool/CMakeLists.txt | 10 | ||||
-rw-r--r-- | tile-tool/big-atlas.cpp | 67 | ||||
-rw-r--r-- | tile-tool/big-atlas.hpp | 33 | ||||
-rw-r--r-- | tile-tool/tile-tool.cpp | 34 | ||||
-rw-r--r-- | tile.cpp | 3 | ||||
-rw-r--r-- | tile.hpp | 6 | ||||
-rw-r--r-- | tile/CMakeLists.txt | 12 | ||||
-rw-r--r-- | tile/serialize.cpp | 17 | ||||
-rw-r--r-- | tile/serialize.hpp | 23 |
24 files changed, 335 insertions, 147 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d5a8477..020b81af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,9 @@ if(NOT BOOTSTRAP_DEPENDS) include_directories(SYSTEM "./include") add_subdirectory(crop-tool) + add_subdirectory(tile-tool) add_subdirectory(anim) + add_subdirectory(tile) corrade_add_resource(game_RESOURCES resources.conf) file(GLOB sources "*.cpp" CONFIGURE_ARGS) diff --git a/anim/serialize.cpp b/anim/serialize.cpp index b0082c3c..83d2b2f9 100644 --- a/anim/serialize.cpp +++ b/anim/serialize.cpp @@ -1,50 +1,12 @@ #include "serialize.hpp" -#include <algorithm> -#include <utility> -#include <fstream> -#include <exception> - #include <Corrade/Utility/Debug.h> #include <Corrade/Utility/DebugStl.h> -#include "../fake-json.hpp" +#include "../json-magnum.hpp" using Corrade::Utility::Error; -namespace nlohmann { - -template<> -struct adl_serializer<Magnum::Vector2i> final { - static void to_json(json& j, const Magnum::Vector2i& x); - static void from_json(const json& j, Magnum::Vector2i& x); -}; - -void adl_serializer<Magnum::Vector2i>::to_json(json& j, const Magnum::Vector2i& val) -{ - char buf[64]; - snprintf(buf, sizeof(buf), "%d x %d", val[0], val[1]); - j = buf; -} - -void adl_serializer<Magnum::Vector2i>::from_json(const json& j, Magnum::Vector2i& val) -{ - std::string str = j; - int x = 0, y = 0, n = 0; - int ret = std::sscanf(str.c_str(), "%d x %d%n", &x, &y, &n); - if (ret != 2 || (std::size_t)n != str.size()) - { - std::string msg; msg.reserve(64 + str.size()); - msg += "failed to parse string '"; - msg += str; - msg += "' as Magnum::Vector2i"; - throw std::invalid_argument(msg); - } - val = { x, y }; -} - -} // namespace nlohmann - #if defined __clang__ || defined __CLION_IDE__ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wweak-vtables" @@ -61,47 +23,10 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(anim, name, nframes, actionframe, fps, groups std::tuple<anim, bool> anim::from_json(const std::filesystem::path& pathname) noexcept { - using namespace nlohmann; - std::ifstream s; - s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); - try { - s.open(pathname, std::ios_base::in); - } catch (const std::ios::failure& e) { - Error{Error::Flag::NoSpace} << "failed to open " << pathname << ": " << e.what(); - return { {}, false }; - } - anim ret; - try { - json j; - s >> j; - using nlohmann::from_json; - from_json(j, ret); - } catch (const std::exception& e) { - Error{Error::Flag::NoSpace} << "failed to parse " << pathname << ": " << e.what(); - return { {}, false }; - } - return { std::move(ret), true }; + return json_helper<anim>::from_json(pathname); } -bool anim::to_json(const std::filesystem::path& pathname) noexcept +bool anim::to_json(const std::filesystem::path& pathname) const noexcept { - try { - nlohmann::json j = *this; - - std::ofstream s; - s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); - try { - s.open(pathname, std::ios_base::out | std::ios_base::trunc); - } catch (const std::ios::failure& e) { - Error{} << "failed to open" << pathname << "for writing:" << e.what(); - return false; - } - s << j.dump(4); - s.flush(); - } catch (const std::exception& e) { - Error{Error::Flag::NoSpace} << "failed writing to " << pathname << ": " << e.what(); - return false; - } - - return true; + return json_helper<anim>::to_json(*this, pathname); } diff --git a/anim/serialize.hpp b/anim/serialize.hpp index a8b13d41..49641fb5 100644 --- a/anim/serialize.hpp +++ b/anim/serialize.hpp @@ -32,7 +32,7 @@ struct anim_group final struct anim final { static std::tuple<anim, bool> from_json(const std::filesystem::path& pathname) noexcept; - [[nodiscard]] bool to_json(const std::filesystem::path& pathname) noexcept; + [[nodiscard]] bool to_json(const std::filesystem::path& pathname) const noexcept; static constexpr int default_fps = 24; std::string name; diff --git a/crop-tool/CMakeLists.txt b/crop-tool/CMakeLists.txt index 42aeac2c..251bcac3 100644 --- a/crop-tool/CMakeLists.txt +++ b/crop-tool/CMakeLists.txt @@ -3,7 +3,7 @@ set(self "${PROJECT_NAME}-crop-tool") include_directories(SYSTEM PRIVATE ${OpenCV_INCLUDE_DIRS}) link_libraries(Corrade::Utility) -link_libraries(game-anim) +link_libraries(${PROJECT_NAME}-anim) file(GLOB sources "*.cpp" CONFIGURE_ARGS) add_executable(${self} ${sources}) diff --git a/anim/atlas.cpp b/crop-tool/atlas.cpp index fe4b5f65..9e16a3cd 100644 --- a/anim/atlas.cpp +++ b/crop-tool/atlas.cpp @@ -1,7 +1,7 @@ #undef NDEBUG #include "atlas.hpp" -#include "serialize.hpp" +#include "../anim/serialize.hpp" #include <cassert> #include <filesystem> diff --git a/anim/atlas.hpp b/crop-tool/atlas.hpp index 5c5e918f..5c5e918f 100644 --- a/anim/atlas.hpp +++ b/crop-tool/atlas.hpp diff --git a/crop-tool/crop-tool.cpp b/crop-tool/crop-tool.cpp index 064f004d..42d54baa 100644 --- a/crop-tool/crop-tool.cpp +++ b/crop-tool/crop-tool.cpp @@ -1,7 +1,7 @@ #undef NDEBUG #include "defs.hpp" -#include "anim/atlas.hpp" +#include "atlas.hpp" #include "anim/serialize.hpp" #include <cassert> diff --git a/fake-json.hpp b/fake-json.hpp deleted file mode 100644 index 57943d37..00000000 --- a/fake-json.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -//#define GAME_REAL_JSON -#if !defined __CLION_IDE__ || defined GAME_REAL_JSON -# include <nlohmann/json.hpp> -#else - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunknown-pragmas" -#pragma ide diagnostic ignored "NotImplementedFunctions" - -namespace nlohmann { - struct json { - template<typename t> operator t() const; - const json& dump(int) const; - template<typename t> json(const t&); - json(); - }; - template<typename t> json& operator>>(const t&, json&); - template<typename t> json& operator<<(t&, const json&); - template<typename t> struct adl_serializer { - static void to_json(json&, const t&); - static void from_json(const json&, t&); - }; - template<typename t> void from_json(const json&, t&); - template<typename t> void to_json(const json&, const t&); -} // namespace nlohmann - -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(...) - -#pragma clang diagnostic pop -#endif diff --git a/json-magnum.hpp b/json-magnum.hpp new file mode 100644 index 00000000..bcd17e0a --- /dev/null +++ b/json-magnum.hpp @@ -0,0 +1,100 @@ +#pragma once + +#include <cstdio> +#include <string> +#include <utility> +#include <fstream> +#include <exception> +#include <nlohmann/json.hpp> +#include <Corrade/Utility/Debug.h> +#include <Corrade/Utility/DebugStl.h> +#include <Magnum/Magnum.h> +#include <Magnum/Math/Vector2.h> + +namespace nlohmann { + +template<> +struct adl_serializer<Magnum::Vector2i> final { + static void to_json(json& j, const Magnum::Vector2i& x); + static void from_json(const json& j, Magnum::Vector2i& x); +}; + +void adl_serializer<Magnum::Vector2i>::to_json(json& j, const Magnum::Vector2i& val) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%d x %d", val[0], val[1]); + j = buf; +} + +void adl_serializer<Magnum::Vector2i>::from_json(const json& j, Magnum::Vector2i& val) +{ + std::string str = j; + int x = 0, y = 0, n = 0; + int ret = std::sscanf(str.c_str(), "%d x %d%n", &x, &y, &n); + if (ret != 2 || (std::size_t)n != str.size()) + { + std::string msg; msg.reserve(64 + str.size()); + msg += "failed to parse string '"; + msg += str; + msg += "' as Magnum::Vector2i"; + throw std::invalid_argument(msg); + } + val = { x, y }; +} + +} // namespace nlohmann + +template<typename t> +struct json_helper final { + [[nodiscard]] static std::tuple<t, bool> from_json(const std::filesystem::path& pathname) noexcept; + [[nodiscard]] static bool to_json(const t& self, const std::filesystem::path& pathname) noexcept; +}; + +template<typename t> +std::tuple<t, bool> json_helper<t>::from_json(const std::filesystem::path& pathname) noexcept { + using namespace nlohmann; + using Corrade::Utility::Error; + std::ifstream s; + s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); + try { + s.open(pathname, std::ios_base::in); + } catch (const std::ios::failure& e) { + Error{Error::Flag::NoSpace} << "failed to open " << pathname << ": " << e.what(); + return { {}, false }; + } + t ret; + try { + json j; + s >> j; + using nlohmann::from_json; + from_json(j, ret); + } catch (const std::exception& e) { + Error{Error::Flag::NoSpace} << "failed to parse " << pathname << ": " << e.what(); + return { {}, false }; + } + return { std::move(ret), true }; +} + +template<typename t> +bool json_helper<t>::to_json(const t& self, const std::filesystem::path& pathname) noexcept { + using Corrade::Utility::Error; + try { + nlohmann::json j = self; + + std::ofstream s; + s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); + try { + s.open(pathname, std::ios_base::out | std::ios_base::trunc); + } catch (const std::ios::failure& e) { + Error{} << "failed to open" << pathname << "for writing:" << e.what(); + return false; + } + s << j.dump(4); + s.flush(); + } catch (const std::exception& e) { + Error{Error::Flag::NoSpace} << "failed writing to " << pathname << ": " << e.what(); + return false; + } + + return true; +} diff --git a/loader-impl.cpp b/loader-impl.cpp index 2008dbae..b761dca4 100644 --- a/loader-impl.cpp +++ b/loader-impl.cpp @@ -1,6 +1,6 @@ #include "defs.hpp" #include "loader.hpp" -#include "texture-atlas.hpp" +#include "tile-atlas.hpp" #include <Corrade/Containers/Optional.h> #include <Corrade/Containers/StringView.h> #include <Corrade/PluginManager/PluginManager.h> @@ -14,18 +14,18 @@ namespace Magnum::Examples { -using atlas_ptr = std::shared_ptr<texture_atlas>; +using atlas_ptr = std::shared_ptr<tile_atlas>; struct loader_impl final : loader_ { const Utility::Resource shader_res{"game/shaders"}; PluginManager::Manager<Trade::AbstractImporter> importer_plugins; Containers::Pointer<Trade::AbstractImporter> tga_importer = - importer_plugins.loadAndInstantiate("TgaImporter"); + importer_plugins.loadAndInstantiate("AnyImageImporter"); PluginManager::Manager<Trade::AbstractImageConverter> image_converter_plugins; Containers::Pointer<Trade::AbstractImageConverter> tga_converter = - image_converter_plugins.loadAndInstantiate("TgaImageConverter"); + image_converter_plugins.loadAndInstantiate("AnyImageConverter"); std::unordered_map<std::string, atlas_ptr> atlas_map; @@ -51,7 +51,7 @@ atlas_ptr loader_impl::tile_atlas(const Containers::StringView& name, Vector2i s if (it != atlas_map.end()) return it->second; auto image = tile_texture(name); - auto atlas = std::make_shared<texture_atlas>(image, size); + auto atlas = std::make_shared<struct tile_atlas>(image, size); atlas_map[name] = atlas; return atlas; } @@ -9,13 +9,13 @@ namespace Magnum::Examples { -struct texture_atlas; +struct tile_atlas; struct loader_ { virtual std::string shader(const Containers::StringView& filename) = 0; virtual Trade::ImageData2D tile_texture(const Containers::StringView& filename) = 0; - virtual std::shared_ptr<texture_atlas> tile_atlas(const Containers::StringView& filename, Vector2i size) = 0; + virtual std::shared_ptr<tile_atlas> tile_atlas(const Containers::StringView& filename, Vector2i size) = 0; static void destroy(); loader_(const loader_&) = delete; @@ -1,4 +1,4 @@ -#include "texture-atlas.hpp" +#include "tile-atlas.hpp" #include "loader.hpp" #include "tile-shader.hpp" #include "defs.hpp" @@ -60,12 +60,12 @@ struct app final : Platform::Application GL::Mesh _mesh, _mesh2; tile_shader _shader; - std::shared_ptr<texture_atlas> atlas = + std::shared_ptr<tile_atlas> atlas = //loader.tile_atlas("../share/game/images/tiles.tga", {8,4}); //loader.tile_atlas("../share/game/images/tiles2.tga", {8,5}); loader.tile_atlas("../share/game/images/metal1.tga", {2, 2}); //loader.tile_atlas("../share/game/images/floor1.tga", {4, 4}); - std::shared_ptr<texture_atlas> atlas2 = + std::shared_ptr<tile_atlas> atlas2 = loader.tile_atlas("../share/game/images/metal2.tga", {2, 2}); std::uint64_t time_ticks = 0, time_freq = SDL_GetPerformanceFrequency(); @@ -130,7 +130,7 @@ app::app(const Arguments& arguments): { Vector3 center{chunk::N/2.f*TILE_SIZE[0], chunk::N/2.f*TILE_SIZE[1], 0}; - texture_atlas::vertex_array_type walls[] = { + tile_atlas::vertex_array_type walls[] = { atlas2->wall_quad_W(center, Vector3(X, Y, Z)), atlas2->wall_quad_N(center, Vector3(X, Y, Z)), atlas2->wall_quad_E(center, Vector3(X, Y, Z)), @@ -140,7 +140,7 @@ app::app(const Arguments& arguments): int k = 0; for (const auto& positions : walls) { - auto texcoords = atlas2->texcoords_for_id(k); + auto texcoords = atlas2->texcoords_for_id(k % atlas2->size()); auto indices_ = atlas2->indices(k); for (unsigned x = 0; x < 4; x++) vertices.push_back({ positions[x], texcoords[x] }); diff --git a/shaders/tile-shader.frag b/shaders/tile-shader.frag index 1cd1cf3d..f75a0478 100644 --- a/shaders/tile-shader.frag +++ b/shaders/tile-shader.frag @@ -1,7 +1,6 @@ precision highp float; layout(location = 2) uniform sampler2D textureData; -layout(location = 1) uniform float y_scale; in vec2 interpolatedTextureCoordinates; diff --git a/texture-atlas.cpp b/tile-atlas.cpp index e8e44900..67d5df7f 100644 --- a/texture-atlas.cpp +++ b/tile-atlas.cpp @@ -1,11 +1,11 @@ -#include "texture-atlas.hpp" +#include "tile-atlas.hpp" #include "defs.hpp" #include <Magnum/ImageView.h> #include <Magnum/GL/TextureFormat.h> namespace Magnum::Examples { -texture_atlas::texture_atlas(const ImageView2D& image, Vector2i dims) : +tile_atlas::tile_atlas(const ImageView2D& image, Vector2i dims) : size_{image.size()}, dims_{dims}, tile_size_{size_ / dims} @@ -22,7 +22,7 @@ texture_atlas::texture_atlas(const ImageView2D& image, Vector2i dims) : .setSubImage(0, {}, image); } -std::array<Vector2, 4> texture_atlas::texcoords_for_id(int id_) const +std::array<Vector2, 4> tile_atlas::texcoords_for_id(int id_) const { CORRADE_INTERNAL_ASSERT(id_ >= 0 && id_ < dims_.product()); Vector2i id = { id_ % dims_[0], id_ / dims_[0] }; @@ -37,9 +37,9 @@ std::array<Vector2, 4> texture_atlas::texcoords_for_id(int id_) const }}; } -using vertex_array_type = texture_atlas::vertex_array_type; +using vertex_array_type = tile_atlas::vertex_array_type; -vertex_array_type texture_atlas::floor_quad(Vector3 center, Vector2 size) +vertex_array_type tile_atlas::floor_quad(Vector3 center, Vector2 size) { float x = size[0]*.5f, y = size[1]*.5f; return {{ @@ -50,7 +50,7 @@ vertex_array_type texture_atlas::floor_quad(Vector3 center, Vector2 size) }}; } -vertex_array_type texture_atlas::wall_quad_W(Vector3 center, Vector3 size) +vertex_array_type tile_atlas::wall_quad_W(Vector3 center, Vector3 size) { float x = size[0]*.5f, y = size[1]*.5f, z = size[2]; return {{ @@ -61,7 +61,7 @@ vertex_array_type texture_atlas::wall_quad_W(Vector3 center, Vector3 size) }}; } -vertex_array_type texture_atlas::wall_quad_S(Vector3 center, Vector3 size) +vertex_array_type tile_atlas::wall_quad_S(Vector3 center, Vector3 size) { float x = size[0]*.5f, y = size[1]*.5f, z = size[2]; return {{ @@ -72,7 +72,7 @@ vertex_array_type texture_atlas::wall_quad_S(Vector3 center, Vector3 size) }}; } -vertex_array_type texture_atlas::wall_quad_E(Vector3 center, Vector3 size) +vertex_array_type tile_atlas::wall_quad_E(Vector3 center, Vector3 size) { float x = size[0]*.5f, y = size[1]*.5f, z = size[2]; return {{ @@ -83,7 +83,7 @@ vertex_array_type texture_atlas::wall_quad_E(Vector3 center, Vector3 size) }}; } -vertex_array_type texture_atlas::wall_quad_N(Vector3 center, Vector3 size) +vertex_array_type tile_atlas::wall_quad_N(Vector3 center, Vector3 size) { float x = size[0]*.5f, y = size[1]*.5f, z = size[2]; return {{ @@ -94,7 +94,7 @@ vertex_array_type texture_atlas::wall_quad_N(Vector3 center, Vector3 size) }}; } -std::array<UnsignedShort, 6> texture_atlas::indices(int N) +std::array<UnsignedShort, 6> tile_atlas::indices(int N) { CORRADE_INTERNAL_ASSERT(N >= 0); using u16 = UnsignedShort; diff --git a/texture-atlas.hpp b/tile-atlas.hpp index e7f8a260..855214b8 100644 --- a/texture-atlas.hpp +++ b/tile-atlas.hpp @@ -5,11 +5,11 @@ namespace Magnum::Examples { -struct texture_atlas final +struct tile_atlas final { using vertex_array_type = std::array<Vector3, 4>; - texture_atlas(const ImageView2D& img, Vector2i dims); + tile_atlas(const ImageView2D& img, Vector2i dims); std::array<Vector2, 4> texcoords_for_id(int id) const; static vertex_array_type floor_quad(Vector3 center, Vector2 size); static vertex_array_type wall_quad_S(Vector3 center, Vector3 size); @@ -21,8 +21,8 @@ struct texture_atlas final constexpr int size() const { return dims_.product(); } constexpr Vector2i tile_size() const { return tile_size_; } - texture_atlas(const texture_atlas&) = delete; - texture_atlas& operator=(const texture_atlas&) = delete; + tile_atlas(const tile_atlas&) = delete; + tile_atlas& operator=(const tile_atlas&) = delete; private: GL::Texture2D tex_; Vector2i size_, dims_, tile_size_; diff --git a/tile-tool/CMakeLists.txt b/tile-tool/CMakeLists.txt new file mode 100644 index 00000000..8f148751 --- /dev/null +++ b/tile-tool/CMakeLists.txt @@ -0,0 +1,10 @@ +find_package(OpenCV QUIET REQUIRED COMPONENTS core imgcodecs imgproc) +set(self "${PROJECT_NAME}-tile-tool") + +include_directories(SYSTEM PRIVATE ${OpenCV_INCLUDE_DIRS}) +link_libraries(Corrade::Utility) +link_libraries(${PROJECT_NAME}-tile) + +file(GLOB sources "*.cpp" CONFIGURE_ARGS) +add_executable(${self} ${sources}) +install(TARGETS ${self} RUNTIME DESTINATION "bin") diff --git a/tile-tool/big-atlas.cpp b/tile-tool/big-atlas.cpp new file mode 100644 index 00000000..a9f877bd --- /dev/null +++ b/tile-tool/big-atlas.cpp @@ -0,0 +1,67 @@ +#undef NDEBUG + +#include "big-atlas.hpp" +#include <cassert> +#include <filesystem> +#include <Corrade/Utility/DebugStl.h> +#include <opencv2/imgproc/imgproc.hpp> +#include <opencv2/imgcodecs/imgcodecs.hpp> + +std::vector<big_atlas_frame> big_atlas_builder::add_atlas(const std::filesystem::path& filename) +{ + using Corrade::Utility::Error; + std::vector<big_atlas_frame> ret; + cv::Mat mat = cv::imread(filename.string(), cv::IMREAD_UNCHANGED); + if (mat.empty() || (mat.type() != CV_8UC4 && mat.type() != CV_8UC3)) + { + Error{} << "failed to load" << filename << "as RGBA32 image"; + return {}; + } + if (mat.type() == CV_8UC3) { + cv::Mat mat2; + cv::cvtColor(mat, mat2, cv::COLOR_RGB2RGBA); + mat = mat2.clone(); + } + + Error{} << "file" << filename; + + assert(mat.cols % TILE_SIZE[0] == 0 && mat.rows % TILE_SIZE[1] == 0); + + for (int y = 0; y + TILE_SIZE[1] <= mat.rows; y += TILE_SIZE[1]) + for (int x = 0; x + TILE_SIZE[0] <= mat.cols; x += TILE_SIZE[0]) + { + Error{} << "convert" << x << y; + cv::Rect roi { x, y, TILE_SIZE[0], TILE_SIZE[1] }; + auto frame = add_frame(mat(roi)); + ret.push_back(frame); + } + + return ret; +} + +big_atlas_frame big_atlas_builder::add_frame(const cv::Mat4b& frame) +{ + auto& row = maybe_next_row(); + big_atlas_frame ret { frame, { row.xpos, row.ypos } }; + row.frames.push_back(ret); + row.xpos += TILE_SIZE[0]; + maxx = std::max(maxx, row.xpos); + return ret; +} + +big_atlas_row& big_atlas_builder::maybe_next_row() +{ + auto& row = rows.back(); + + if (row.xpos + TILE_SIZE[0] > MAX_TEXTURE_SIZE[0]) + { + ypos += TILE_SIZE[1]; + rows.emplace_back(); + auto& row = rows.back(); + row.ypos = ypos; + + return row; + } + else + return row; +} diff --git a/tile-tool/big-atlas.hpp b/tile-tool/big-atlas.hpp new file mode 100644 index 00000000..77961be0 --- /dev/null +++ b/tile-tool/big-atlas.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include <Magnum/Magnum.h> +#include <Magnum/Math/Vector2.h> +#include <opencv2/core/mat.hpp> + +namespace std::filesystem { class path; } + +struct big_atlas_frame { + cv::Mat4b frame; + Magnum::Vector2i position; +}; + +struct big_atlas_row { + std::vector<big_atlas_frame> frames; + int xpos = 0, ypos = 0; +}; + +struct big_atlas_builder { + [[nodiscard]] std::vector<big_atlas_frame> add_atlas(const std::filesystem::path& filename); + big_atlas_frame add_frame(const cv::Mat4b& frame); + big_atlas_row& maybe_next_row(); + +private: + static constexpr Magnum::Vector2i TILE_SIZE = { 100, 100 }, + MAX_TEXTURE_SIZE = { 512, 512 }; + + std::vector<big_atlas_row> rows = {{}}; + int ypos = 0, maxx = 0; + + static_assert(!!TILE_SIZE[0] && !!TILE_SIZE[1] && !!MAX_TEXTURE_SIZE[0] && !!MAX_TEXTURE_SIZE[1]); + static_assert(MAX_TEXTURE_SIZE[0] >= TILE_SIZE[0] && MAX_TEXTURE_SIZE[1] >= TILE_SIZE[1]); +}; diff --git a/tile-tool/tile-tool.cpp b/tile-tool/tile-tool.cpp new file mode 100644 index 00000000..edc882ad --- /dev/null +++ b/tile-tool/tile-tool.cpp @@ -0,0 +1,34 @@ +#include "big-atlas.hpp" +#include "tile/serialize.hpp" +#include <tuple> +#include <filesystem> +#include <Corrade/Utility/Arguments.h> + +using Corrade::Utility::Arguments; + +struct options final { + std::filesystem::path input_dir, output_file; +}; + +static std::tuple<options, Arguments, bool> parse_cmdline(int argc, const char* const* argv) noexcept +{ + Corrade::Utility::Arguments args{}; + args.addOption('o', "output") + .addArrayArgument("input"); + args.parse(argc, argv); + options opts; + opts.input_dir = args.value<std::string>("input"); + + if (opts.input_dir.empty()) + opts.output_file = opts.input_dir.parent_path() / "big-atlas.json"; + + return { std::move(opts), std::move(args), true }; +} + +int main(int argc, char** argv) +{ + big_atlas_builder builder; + builder.add_atlas("images/metal1.png"); + builder.add_atlas("images/metal2.png"); + return 0; +} @@ -1,8 +1,5 @@ #include "tile.hpp" -#include <limits> namespace Magnum::Examples { -world::world() = default; - } // namespace Magnum::Examples @@ -1,5 +1,5 @@ #pragma once -#include "texture-atlas.hpp" +#include "tile-atlas.hpp" #include "hash.hpp" #include "defs.hpp" @@ -17,7 +17,7 @@ static constexpr Vector3 TILE_SIZE = { 50, 50, 50 }; struct tile_image final { - std::shared_ptr<texture_atlas> atlas; + std::shared_ptr<tile_atlas> atlas; std::uint8_t variant = 0xff; explicit operator bool() const noexcept { return !!atlas; } @@ -140,7 +140,7 @@ struct world final { static_assert(sizeof(chunk_coords::x) <= sizeof(std::size_t)/2); - explicit world(); + explicit world() = default; template<typename F> std::shared_ptr<chunk> ensure_chunk(chunk_coords xy, F&& fun); private: diff --git a/tile/CMakeLists.txt b/tile/CMakeLists.txt new file mode 100644 index 00000000..73cb2b58 --- /dev/null +++ b/tile/CMakeLists.txt @@ -0,0 +1,12 @@ +find_package(OpenCV QUIET REQUIRED COMPONENTS core imgcodecs imgproc) +find_package(nlohmann_json QUIET REQUIRED) + +set(self "${PROJECT_NAME}-tile") + +include_directories(SYSTEM PRIVATE ${OpenCV_INCLUDE_DIRS}) +link_libraries(opencv_imgproc opencv_imgcodecs opencv_core) +link_libraries(Magnum::Magnum nlohmann_json::nlohmann_json) + +file(GLOB sources "*.cpp" CONFIGURE_ARGS) +add_library(${self} STATIC ${sources}) + diff --git a/tile/serialize.cpp b/tile/serialize.cpp new file mode 100644 index 00000000..4043c8de --- /dev/null +++ b/tile/serialize.cpp @@ -0,0 +1,17 @@ +#include "serialize.hpp" +#include <nlohmann/json.hpp> +#include "json-magnum.hpp" + +std::tuple<big_atlas, bool> big_atlas::from_json(const std::filesystem::path& pathname) noexcept +{ + +} + +bool big_atlas::to_json(const std::filesystem::path& pathname) noexcept +{ + +} + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(big_atlas_tile, position) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(big_atlas_entry, tiles) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(big_atlas, entries) diff --git a/tile/serialize.hpp b/tile/serialize.hpp new file mode 100644 index 00000000..c28aa934 --- /dev/null +++ b/tile/serialize.hpp @@ -0,0 +1,23 @@ +#include <string> +#include <vector> +#include <tuple> +#include <unordered_map> +#include <Magnum/Magnum.h> +#include <Magnum/Math/Vector2.h> + +namespace std::filesystem { class path; } + +struct big_atlas_tile final { + Magnum::Vector2i position; +}; + +struct big_atlas_entry final { + std::vector<big_atlas_tile> tiles; +}; + +struct big_atlas final { + static std::tuple<big_atlas, bool> from_json(const std::filesystem::path& pathname) noexcept; + [[nodiscard]] bool to_json(const std::filesystem::path& pathname) noexcept; + + std::unordered_map<std::string, big_atlas_entry> entries; +}; |