From dc4f667f7b1af7e936ef9911863a90b70d917cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 22:37:32 +0100 Subject: [PATCH] MeshTools: added interleaveInto(). Basically a version of interleave() which takes existing buffer instead of creating new zero-initialized one. The last bit needed for real runtime usage. --- src/Magnum/MeshTools/Interleave.h | 34 ++++++++++++++-- src/Magnum/MeshTools/Test/InterleaveTest.cpp | 41 +++++++++++++++++++- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index 0c7412dd1..0c7d10b3f 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Function @ref Magnum::MeshTools::interleave() + * @brief Function @ref Magnum::MeshTools::interleave(), @ref Magnum::MeshTools::interleaveInto() */ #include @@ -121,8 +121,8 @@ std::size_t stride; Containers::Array data; std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, weights, 2, textureCoordinates, 1); @endcode -This way vertex stride is 24 bytes, without gaps it would be 21 bytes, causing -possible performance loss. +All gap bytes are set zero. This way vertex stride is 24 bytes, without gaps it +would be 21 bytes, causing possible performance loss. @attention The function expects that all arrays have the same size. @@ -132,7 +132,9 @@ possible performance loss. will be `std::vector` or `std::array`. See also @ref interleave(Mesh&, Buffer&, BufferUsage, const T&...), -which writes the interleaved array directly into buffer of given mesh. +which writes the interleaved array directly into buffer of given mesh or +@ref interleaveInto() which writes the data into existing buffer instead of +creating new one. */ /* enable_if to avoid clash with overloaded function below */ template typename std::enable_if::value, std::tuple>>::type interleave(const T& first, const U&... next) { @@ -151,6 +153,30 @@ template typename std::enable_if::va } else return std::make_tuple(0, stride, nullptr); } +/** +@brief %Interleave vertex attributes into existing buffer + +Unlike @ref interleave() this function interleaves the data into existing +buffer and leaves gaps untouched instead of zero-initializing them. This +function can thus be used for interleaving data depending on runtime +parameters. + +@attention Similarly to @ref interleave(), this function expects that all + arrays have the same size. The passed buffer must also be large enough to + contain the interleaved data. +*/ +template std::tuple interleaveInto(Containers::ArrayReference buffer, const T& first, const U&... next) { + /* Verify expected buffer size */ + const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...); + const std::size_t stride = Implementation::Stride{}(first, next...); + CORRADE_ASSERT(attributeCount*stride <= buffer.size(), "MeshTools::interleaveInto(): the data buffer is too small, expected" << attributeCount*stride << "but got" << buffer.size(), {}); + + /* Write data */ + Implementation::writeInterleaved(stride, buffer.begin(), first, next...); + + return std::make_tuple(attributeCount, stride); +} + /** @brief %Interleave vertex attributes, write them to array buffer and configure the mesh @param mesh Output mesh diff --git a/src/Magnum/MeshTools/Test/InterleaveTest.cpp b/src/Magnum/MeshTools/Test/InterleaveTest.cpp index 55ad00b4b..a4f43878e 100644 --- a/src/Magnum/MeshTools/Test/InterleaveTest.cpp +++ b/src/Magnum/MeshTools/Test/InterleaveTest.cpp @@ -42,6 +42,8 @@ class InterleaveTest: public Corrade::TestSuite::Tester { void strideGaps(); void write(); void writeGaps(); + + void interleaveInto(); }; InterleaveTest::InterleaveTest() { @@ -50,7 +52,9 @@ InterleaveTest::InterleaveTest() { &InterleaveTest::stride, &InterleaveTest::strideGaps, &InterleaveTest::write, - &InterleaveTest::writeGaps}); + &InterleaveTest::writeGaps, + + &InterleaveTest::interleaveInto}); } void InterleaveTest::attributeCount() { @@ -137,6 +141,41 @@ void InterleaveTest::writeGaps() { } } +void InterleaveTest::interleaveInto() { + std::size_t attributeCount; + std::size_t stride; + auto data = Containers::Array::from( + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77 + ); + + std::tie(attributeCount, stride) = MeshTools::interleaveInto(data, + 2, std::vector{4, 5, 6, 7}, 1, std::vector{0, 1, 2, 3}, 3); + + CORRADE_COMPARE(attributeCount, std::size_t{4}); + CORRADE_COMPARE(stride, std::size_t{12}); + + if(!Utility::Endianness::isBigEndian()) { + /* _______gap, int___________________, _gap, short_____, _____________gap */ + CORRADE_COMPARE(std::vector(data.begin(), data.end()), (std::vector{ + 0x11, 0x33, 0x04, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x05, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x06, 0x00, 0x00, 0x00, 0x55, 0x02, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x07, 0x00, 0x00, 0x00, 0x55, 0x03, 0x00, 0x33, 0x55, 0x77 + })); + } else { + /* _______gap, ___________________int, _gap, _____short, _____________gap */ + CORRADE_COMPARE(std::vector(data.begin(), data.end()), (std::vector{ + 0x11, 0x33, 0x00, 0x00, 0x00, 0x04, 0x55, 0x00, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x00, 0x00, 0x00, 0x05, 0x55, 0x00, 0x01, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x00, 0x00, 0x00, 0x06, 0x55, 0x00, 0x02, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x00, 0x00, 0x00, 0x07, 0x55, 0x00, 0x03, 0x33, 0x55, 0x77 + })); + } +} + }}} CORRADE_TEST_MAIN(Magnum::MeshTools::Test::InterleaveTest)