diff --git a/src/MeshTools/Interleave.h b/src/MeshTools/Interleave.h index 18d8eec7b..faf0506cd 100644 --- a/src/MeshTools/Interleave.h +++ b/src/MeshTools/Interleave.h @@ -36,7 +36,7 @@ class Interleave { public: inline Interleave(): _attributeCount(0), _stride(0), _data(nullptr) {} - template std::tuple operator()(const std::vector&... attributes) { + template std::tuple operator()(const T&... attributes) { /* Compute buffer size and stride */ _attributeCount = attributeCount(attributes...); if(_attributeCount) { @@ -52,7 +52,7 @@ class Interleave { return std::make_tuple(_attributeCount, _stride, _data); } - template void operator()(Mesh* mesh, Buffer* buffer, Buffer::Usage usage, const std::vector&... attributes) { + template void operator()(Mesh* mesh, Buffer* buffer, Buffer::Usage usage, const T&... attributes) { CORRADE_ASSERT(mesh->isInterleaved(buffer), "MeshTools::interleave(): the buffer is not interleaved, nothing done", ) operator()(attributes...); @@ -63,23 +63,24 @@ class Interleave { delete[] _data; } - template inline static size_t attributeCount(const std::vector& first, const std::vector&... next) { + template inline static size_t attributeCount(const T& first, const U&... next) { CORRADE_ASSERT(sizeof...(next) == 0 || attributeCount(next...) == first.size(), "MeshTools::interleave(): attribute arrays don't have the same length, nothing done.", 0) return first.size(); } - template inline static size_t stride(const std::vector& first, const std::vector&... next) { - return sizeof(T) + stride(next...); + template inline static size_t stride(const T& first, const U&... next) { + return sizeof(typename T::value_type) + stride(next...); } private: - template void write(char* startingOffset, const std::vector& first, const std::vector&... next) { + template void write(char* startingOffset, const T& first, const U&... next) { /* Copy the data to the buffer */ - for(size_t i = 0; i != _attributeCount; ++i) - memcpy(startingOffset+i*_stride, reinterpret_cast(&first[i]), sizeof(T)); + auto it = first.begin(); + for(size_t i = 0; i != _attributeCount; ++i, ++it) + memcpy(startingOffset+i*_stride, reinterpret_cast(&*it), sizeof(typename T::value_type)); - write(startingOffset+sizeof(T), next...); + write(startingOffset+sizeof(typename T::value_type), next...); } /* Terminator functions for recursive calls */ @@ -101,7 +102,8 @@ class Interleave { /** @brief %Interleave vertex attributes -@param attributes Attribute arrays +@param attribute First attribute array +@param attributes Next attribute arrays @return Attribute count, stride and interleaved attribute array. Deleting the array is user responsibility. @@ -110,23 +112,31 @@ so data for each attribute are in continuous place in memory. Size of the data buffer can be computed from attribute count and stride, as shown below. Example usage: @code +std::vector vertices; +std::vector textureCoordinates; size_t attributeCount; size_t stride; char* data; -std::tie(attributeCount, stride, data) = MeshTools::interleave(attributes); +std::tie(attributeCount, stride, data) = MeshTools::interleave(vertices, textureCoordinates); size_t dataSize = attributeCount*stride; // ... delete[] data; @endcode +The only requirements to attribute array type is that it must have typedef +`T::value_type`, forward iterator (to be used with range-based for) and +function `size()` returning count of elements. In most cases it will be +`std::vector` or `std::array`. + See also interleave(Mesh*, Buffer*, Buffer::Usage, const std::vector&...), which writes the interleaved array directly into buffer of given mesh. -@attention Each vector should have the same size, if not, resulting array has - zero length. +@attention Each passed array should have the same size, if not, resulting + array has zero length. */ -template inline std::tuple interleave(const std::vector&... attributes) { - return Implementation::Interleave()(attributes...); +/* enable_if to avoid clash with overloaded function below */ +template inline typename std::enable_if::value, std::tuple>::type interleave(const T& attribute, const U&... attributes) { + return Implementation::Interleave()(attribute, attributes...); } /** @@ -136,15 +146,14 @@ template inline std::tuple interleave(const s @param buffer Output array buffer @param usage Array buffer usage -The same as interleave(const std::vector&...), but this function writes -the output to given array buffer and updates vertex count in the mesh -accordingly. +The same as interleave(const T&...), but this function writes the output to +given array buffer and updates vertex count in the mesh accordingly. @attention The buffer must be set as interleaved (see Mesh::addBuffer()), otherwise this function does nothing. Binding the attributes to shader is left to user. */ -template inline void interleave(Mesh* mesh, Buffer* buffer, Buffer::Usage usage, const std::vector&... attributes) { +template inline void interleave(Mesh* mesh, Buffer* buffer, Buffer::Usage usage, const T&... attributes) { return Implementation::Interleave()(mesh, buffer, usage, attributes...); }