From d7d5cd4265aab0b939b57ea7237b56f2f5840642 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 11 Mar 2023 12:07:29 +0000 Subject: Initial version of texture packer Determines where a collection of smaller textures can be tiled into a single bigger image. Probably non-optimal. --- test/test-assetFactory.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'test') diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index 204ffb3..ad62a93 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -7,6 +7,7 @@ #include "assetFactory/assetFactory.h" #include "assetFactory/object.h" +#include "assetFactory/texturePacker.h" #include "game/vehicles/railVehicle.h" #include "game/vehicles/railVehicleClass.h" #include "gfx/gl/sceneRenderer.h" @@ -125,3 +126,45 @@ BOOST_AUTO_TEST_CASE(parseX11RGB) BOOST_CHECK_CLOSE_VEC(parsedColours.at("slategrey"), AssetFactory::Colour(0.44F, 0.5, 0.56F)); BOOST_CHECK_CLOSE_VEC(parsedColours.at("lightsteelblue1"), AssetFactory::Colour(0.79, 0.88, 1)); } + +BOOST_AUTO_TEST_CASE(texturePacker) +{ + TexturePacker tp {{ + {10, 10}, + {10, 10}, + {10, 10}, + {100, 10}, + {10, 200}, + {5, 5}, + }}; + BOOST_CHECK_EQUAL(TexturePacker::Size(128, 256), tp.minSize()); + const auto result = tp.pack(); +} + +BOOST_AUTO_TEST_CASE(texturePacker_many, *boost::unit_test::timeout(5)) +{ + std::vector images(256); + std::fill(images.begin(), images.end(), TexturePacker::Image {32, 32}); + const auto totalSize = std::accumulate(images.begin(), images.end(), 0U, [](auto t, const auto & i) { + return t + TexturePacker::area(i); + }); + TexturePacker tp {images}; + BOOST_CHECK_EQUAL(TexturePacker::Size(32, 32), tp.minSize()); + const auto result = tp.pack(); + BOOST_CHECK_EQUAL(result.first.size(), images.size()); + BOOST_CHECK_GE(TexturePacker::area(result.second), TexturePacker::area(images.front()) * images.size()); + BOOST_CHECK_EQUAL(totalSize, TexturePacker::area(result.second)); +} + +BOOST_AUTO_TEST_CASE(texturePacker_many_random, *boost::unit_test::timeout(5)) +{ + std::vector images(2048); + std::mt19937 gen(std::random_device {}()); + std::uniform_int_distribution<> dim {1, 10}; + std::generate(images.begin(), images.end(), [&dim, &gen]() { + return TexturePacker::Image {2 ^ dim(gen), 2 ^ dim(gen)}; + }); + TexturePacker tp {images}; + const auto result = tp.pack(); + BOOST_CHECK_EQUAL(result.first.size(), images.size()); +} -- cgit v1.2.3 From 2d6772cb1c592e4bd75be40f1fdfa924bbbc3c07 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Tue, 14 Mar 2023 18:14:54 +0000 Subject: Add postLoad support to persistence --- lib/persistence.cpp | 5 +++++ lib/persistence.h | 10 ++++++++-- test/test-persistence.cpp | 7 +++++++ test/testStructures.cpp | 6 ++++++ test/testStructures.h | 3 +++ 5 files changed, 29 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/lib/persistence.cpp b/lib/persistence.cpp index 8c7c6a4..06e40c7 100644 --- a/lib/persistence.cpp +++ b/lib/persistence.cpp @@ -41,6 +41,11 @@ namespace Persistence { return ss.str(); } + void + Persistable::postLoad() + { + } + PersistenceSelect::PersistenceSelect(const std::string & n) : name {n} { } PersistenceStore::NameAction diff --git a/lib/persistence.h b/lib/persistence.h index 35d60ca..1cb3af0 100644 --- a/lib/persistence.h +++ b/lib/persistence.h @@ -311,8 +311,9 @@ namespace Persistence { void endObject(Persistence::Stack & stk) override { + // TODO test with unique_ptr map.emplace(std::invoke(Key, s), std::move(s)); - stk.pop(); + Persistence::SelectionT::endObject(stk); } private: @@ -327,8 +328,9 @@ namespace Persistence { void endObject(Persistence::Stack & stk) override { + // TODO test with unique_ptr container.emplace_back(std::move(s)); - stk.pop(); + Persistence::SelectionT::endObject(stk); } private: @@ -342,6 +344,7 @@ namespace Persistence { DEFAULT_MOVE_COPY(Persistable); virtual bool persist(PersistenceStore & store) = 0; + virtual void postLoad(); [[nodiscard]] virtual std::string getId() const; @@ -484,6 +487,9 @@ namespace Persistence { endObject(Stack & stk) override { make_default_as_needed(this->v); + if (this->v) { + this->v->postLoad(); + } stk.pop(); } diff --git a/test/test-persistence.cpp b/test/test-persistence.cpp index a72c481..38bbf2f 100644 --- a/test/test-persistence.cpp +++ b/test/test-persistence.cpp @@ -34,6 +34,7 @@ struct JPP { BOOST_FIXTURE_TEST_CASE(load_object, JPP) { auto to = load_json>(FIXTURESDIR "json/load_object.json"); + BOOST_CHECK_EQUAL(to->postLoadCalled, 1); BOOST_CHECK_CLOSE(to->flt, 3.14, 0.01); BOOST_CHECK_EQUAL(to->str, "Lovely string"); BOOST_CHECK_EQUAL(to->bl, true); @@ -69,6 +70,7 @@ BOOST_FIXTURE_TEST_CASE(load_object, JPP) BOOST_FIXTURE_TEST_CASE(load_nested_object, JPP) { auto to = load_json>(FIXTURESDIR "json/nested.json"); + BOOST_CHECK_EQUAL(to->postLoadCalled, 1); BOOST_CHECK_EQUAL(to->flt, 1.F); BOOST_CHECK_EQUAL(to->str, "one"); BOOST_REQUIRE(to->ptr); @@ -86,6 +88,7 @@ BOOST_FIXTURE_TEST_CASE(load_nested_object, JPP) BOOST_FIXTURE_TEST_CASE(load_implicit_object, JPP) { auto to = load_json>(FIXTURESDIR "json/implicit.json"); + BOOST_CHECK_EQUAL(to->postLoadCalled, 1); BOOST_CHECK(to->ptr); BOOST_CHECK_EQUAL(to->flt, 1.F); BOOST_CHECK_EQUAL(to->ptr->str, "trigger"); @@ -95,6 +98,7 @@ BOOST_FIXTURE_TEST_CASE(load_implicit_object, JPP) BOOST_FIXTURE_TEST_CASE(load_empty_object, JPP) { auto to = load_json>(FIXTURESDIR "json/empty.json"); + BOOST_CHECK_EQUAL(to->postLoadCalled, 1); BOOST_CHECK_EQUAL(to->flt, 1.F); BOOST_CHECK(to->ptr); BOOST_CHECK_EQUAL(to->str, "after"); @@ -119,6 +123,7 @@ BOOST_FIXTURE_TEST_CASE(load_obj_no_such_type, JPP) BOOST_FIXTURE_TEST_CASE(load_abs_object, JPP) { auto to = load_json>(FIXTURESDIR "json/abs.json"); + BOOST_CHECK_EQUAL(to->postLoadCalled, 1); BOOST_REQUIRE(to->aptr); BOOST_CHECK_NO_THROW(to->aptr->dummy()); BOOST_CHECK_EQUAL(to->aptr->base, "set base"); @@ -130,6 +135,7 @@ BOOST_FIXTURE_TEST_CASE(load_abs_object, JPP) BOOST_FIXTURE_TEST_CASE(load_vector_ptr, JPP) { auto to = load_json>(FIXTURESDIR "json/vector_ptr.json"); + BOOST_CHECK_EQUAL(to->postLoadCalled, 1); BOOST_CHECK(to->str.empty()); BOOST_CHECK_EQUAL(to->vptr.size(), 4); BOOST_CHECK_EQUAL(to->vptr.at(0)->str, "type"); @@ -141,6 +147,7 @@ BOOST_FIXTURE_TEST_CASE(load_vector_ptr, JPP) BOOST_FIXTURE_TEST_CASE(test_conversion, JPP) { auto to = load_json>(FIXTURESDIR "json/conv.json"); + BOOST_CHECK_EQUAL(to->postLoadCalled, 1); BOOST_REQUIRE(to); BOOST_CHECK_EQUAL(to->bl, true); BOOST_CHECK_EQUAL(to->flt, 3.14F); diff --git a/test/testStructures.cpp b/test/testStructures.cpp index 8305078..469ec37 100644 --- a/test/testStructures.cpp +++ b/test/testStructures.cpp @@ -42,6 +42,12 @@ TestObject::persist(Persistence::PersistenceStore & store) && STORE_MEMBER(vptr); } +void +TestObject::postLoad() +{ + postLoadCalled++; +} + bool SharedTestObject::persist(Persistence::PersistenceStore & store) { diff --git a/test/testStructures.h b/test/testStructures.h index 666562e..6966052 100644 --- a/test/testStructures.h +++ b/test/testStructures.h @@ -39,7 +39,10 @@ struct TestObject : public Persistence::Persistable { std::unique_ptr aptr; std::vector> vptr; + unsigned int postLoadCalled {}; + bool persist(Persistence::PersistenceStore & store) override; + void postLoad() override; }; struct SharedTestObject : public Persistence::Persistable { -- cgit v1.2.3 From 7867a8a91a2210e1fb4f4bfb71d24ef4c1e8bd86 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 17 Mar 2023 00:35:57 +0000 Subject: Update test/fixture/resource dependencies --- test/Jamfile.jam | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/Jamfile.jam b/test/Jamfile.jam index e178573..e38a80e 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -1,5 +1,6 @@ import testing ; import sequence ; +import path : glob-tree ; lib boost_unit_test_framework ; lib benchmark ; @@ -48,12 +49,12 @@ run test-maths.cpp ; run test-lib.cpp ; run test-geo.cpp ; run test-network.cpp ; -run test-persistence.cpp : -- : [ sequence.insertion-sort [ glob fixtures/json/*.json fixtures/json/bad/*.json ] ] : test ; +run test-persistence.cpp : -- : [ sequence.insertion-sort [ glob-tree fixtures : *.json ] ] : test ; run test-text.cpp ; run test-enumDetails.cpp ; run test-render.cpp : : : test ; run test-glContextBhvr.cpp ; -run test-assetFactory.cpp : -- : ../res/brush47.xml : test ; +run test-assetFactory.cpp : -- : [ sequence.insertion-sort [ glob-tree $(res) : *.xml *.png ] fixtures/rgb.txt ] : test ; run perf-assetFactory.cpp : : : benchmark test ; run perf-persistence.cpp : : : benchmark test ; compile test-static-enumDetails.cpp ; -- cgit v1.2.3 From c915f1bcd46144578fad464e52b5a6013dc98de8 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 17 Mar 2023 02:05:42 +0000 Subject: Fix texture packer return value so positions match inputs --- assetFactory/texturePacker.cpp | 15 +++++++++------ assetFactory/texturePacker.h | 5 +++-- test/test-assetFactory.cpp | 5 +++-- 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'test') diff --git a/assetFactory/texturePacker.cpp b/assetFactory/texturePacker.cpp index 31c9a0e..68a6010 100644 --- a/assetFactory/texturePacker.cpp +++ b/assetFactory/texturePacker.cpp @@ -1,14 +1,16 @@ #include "texturePacker.h" +#include "collections.hpp" #include #include #include #include #include -TexturePacker::TexturePacker(std::vector in) : inputImages {std::move(in)} +TexturePacker::TexturePacker(std::span in) : + inputImages {std::move(in)}, sortedIndexes {vectorOfN(inputImages.size(), size_t {})} { - std::sort(inputImages.rbegin(), inputImages.rend(), [](const auto & a, const auto & b) { - return area(a) < area(b); + std::sort(sortedIndexes.rbegin(), sortedIndexes.rend(), [this](const auto a, const auto b) { + return area(inputImages[a]) < area(inputImages[b]); }); } @@ -24,15 +26,16 @@ TexturePacker::pack(Size size) const using Spaces = std::set; Spaces spaces {{{}, size}}; - Positions result; - for (const auto & image : inputImages) { + Positions result(inputImages.size()); + for (const auto & idx : sortedIndexes) { + const auto & image = inputImages[idx]; if (const auto spaceItr = std::find_if(spaces.begin(), spaces.end(), [image](const Space & s) { return image.x <= s.size.x && image.y <= s.size.y; }); spaceItr != spaces.end()) { auto space = *spaceItr; - result.push_back(space.position); + result[idx] = space.position; spaces.erase(spaceItr); if (space.size.x > image.x) { spaces.emplace(Position {space.position.x + image.x, space.position.y}, diff --git a/assetFactory/texturePacker.h b/assetFactory/texturePacker.h index 8e2061b..7e00f1a 100644 --- a/assetFactory/texturePacker.h +++ b/assetFactory/texturePacker.h @@ -23,7 +23,7 @@ public: using Positions = std::vector; using Result = std::pair; - TexturePacker(std::vector); + TexturePacker(std::span); Result pack(Size) const; Result pack() const; @@ -32,5 +32,6 @@ public: static decltype(Size::x) area(const Size & size); private: - std::vector inputImages; + std::span inputImages; + std::vector sortedIndexes; }; diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index ad62a93..d71fa9b 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -129,14 +129,15 @@ BOOST_AUTO_TEST_CASE(parseX11RGB) BOOST_AUTO_TEST_CASE(texturePacker) { - TexturePacker tp {{ + std::vector input { {10, 10}, {10, 10}, {10, 10}, {100, 10}, {10, 200}, {5, 5}, - }}; + }; + TexturePacker tp {input}; BOOST_CHECK_EQUAL(TexturePacker::Size(128, 256), tp.minSize()); const auto result = tp.pack(); } -- cgit v1.2.3 From e1c0ba6226225c026b35e67ec27647baaa64b2a8 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 19 Mar 2023 23:08:26 +0000 Subject: Make perf tests depend on their functional equivalent --- test/Jamfile.jam | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/Jamfile.jam b/test/Jamfile.jam index e38a80e..bf1c408 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -55,8 +55,8 @@ run test-enumDetails.cpp ; run test-render.cpp : : : test ; run test-glContextBhvr.cpp ; run test-assetFactory.cpp : -- : [ sequence.insertion-sort [ glob-tree $(res) : *.xml *.png ] fixtures/rgb.txt ] : test ; -run perf-assetFactory.cpp : : : benchmark test ; -run perf-persistence.cpp : : : benchmark test ; +run perf-assetFactory.cpp : : : benchmark test test-assetFactory ; +run perf-persistence.cpp : : : benchmark test test-persistence ; compile test-static-enumDetails.cpp ; compile test-static-stream_support.cpp ; explicit perf-assetFactory ; -- cgit v1.2.3 From b76ad768ceddc2777044d0f7128d292332a75353 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 7 Apr 2023 23:49:36 +0100 Subject: Add timeouts to asset factory tests Yes, I made some infinite loops a few times --- test/test-assetFactory.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index d71fa9b..54168aa 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -68,7 +68,7 @@ private: }; BOOST_FIXTURE_TEST_SUITE(m, FactoryFixture); -BOOST_AUTO_TEST_CASE(brush47xml) +BOOST_AUTO_TEST_CASE(brush47xml, *boost::unit_test::timeout(5)) { auto mf = AssetFactory::loadXML(RESDIR "/brush47.xml"); BOOST_REQUIRE(mf); @@ -118,7 +118,7 @@ BOOST_DATA_TEST_CASE(normalizeColourName, BOOST_CHECK_EQUAL(in, exp); } -BOOST_AUTO_TEST_CASE(parseX11RGB) +BOOST_AUTO_TEST_CASE(parseX11RGB, *boost::unit_test::timeout(5)) { const auto parsedColours = AssetFactory::parseX11RGB(FIXTURESDIR "rgb.txt"); BOOST_REQUIRE_EQUAL(parsedColours.size(), 20); @@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE(parseX11RGB) BOOST_CHECK_CLOSE_VEC(parsedColours.at("lightsteelblue1"), AssetFactory::Colour(0.79, 0.88, 1)); } -BOOST_AUTO_TEST_CASE(texturePacker) +BOOST_AUTO_TEST_CASE(texturePacker, *boost::unit_test::timeout(5)) { std::vector input { {10, 10}, -- cgit v1.2.3