Browse Source

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.
pull/51/head
Vladimír Vondruš 12 years ago
parent
commit
dc4f667f7b
  1. 34
      src/Magnum/MeshTools/Interleave.h
  2. 41
      src/Magnum/MeshTools/Test/InterleaveTest.cpp

34
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 <cstring>
@ -121,8 +121,8 @@ std::size_t stride;
Containers::Array<char> 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<class T, class ...U> typename std::enable_if<!std::is_same<T, Mesh>::value, std::tuple<std::size_t, std::size_t, Containers::Array<char>>>::type interleave(const T& first, const U&... next) {
@ -151,6 +153,30 @@ template<class T, class ...U> typename std::enable_if<!std::is_same<T, Mesh>::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<class T, class ...U> std::tuple<std::size_t, std::size_t> interleaveInto(Containers::ArrayReference<char> 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

41
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<char>::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<Int>{4, 5, 6, 7}, 1, std::vector<Short>{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<char>(data.begin(), data.end()), (std::vector<char>{
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<char>(data.begin(), data.end()), (std::vector<char>{
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)

Loading…
Cancel
Save