Browse Source

MeshTools: return Containers::Array instead of pointer from compressIndices().

This is source-incompatible change, but this function probably wasn't
used much in user code, rather its Mesh/Buffer convenience overload.

Actually Containers::Array<char> has _implicit_ conversion operator to
char*, but this should not be an issue, as the conversion is not allowed
on rvalue references, thus the following code shouldn't compile at all.
Not available on GCC < 4.8.1, though.

        // ...
        char* data;
        std::tie(..., data) = MeshTools::compressIndices(...);
pull/34/head
Vladimír Vondruš 13 years ago
parent
commit
b0c0e2d92d
  1. 18
      src/MeshTools/CompressIndices.cpp
  2. 13
      src/MeshTools/CompressIndices.h
  3. 22
      src/MeshTools/Test/CompressIndicesTest.cpp

18
src/MeshTools/CompressIndices.cpp

@ -38,17 +38,17 @@ template<> constexpr Mesh::IndexType indexType<UnsignedByte>() { return Mesh::In
template<> constexpr Mesh::IndexType indexType<UnsignedShort>() { return Mesh::IndexType::UnsignedShort; } template<> constexpr Mesh::IndexType indexType<UnsignedShort>() { return Mesh::IndexType::UnsignedShort; }
template<> constexpr Mesh::IndexType indexType<UnsignedInt>() { return Mesh::IndexType::UnsignedInt; } template<> constexpr Mesh::IndexType indexType<UnsignedInt>() { return Mesh::IndexType::UnsignedInt; }
template<class T> inline std::tuple<std::size_t, Mesh::IndexType, char*> compress(const std::vector<UnsignedInt>& indices) { template<class T> inline std::tuple<std::size_t, Mesh::IndexType, Containers::Array<char>> compress(const std::vector<UnsignedInt>& indices) {
char* buffer = new char[indices.size()*sizeof(T)]; Containers::Array<char> buffer(indices.size()*sizeof(T));
for(std::size_t i = 0; i != indices.size(); ++i) { for(std::size_t i = 0; i != indices.size(); ++i) {
T index = static_cast<T>(indices[i]); T index = static_cast<T>(indices[i]);
std::memcpy(buffer+i*sizeof(T), &index, sizeof(T)); std::memcpy(buffer.begin()+i*sizeof(T), &index, sizeof(T));
} }
return std::make_tuple(indices.size(), indexType<T>(), buffer); return std::make_tuple(indices.size(), indexType<T>(), std::move(buffer));
} }
std::tuple<std::size_t, Mesh::IndexType, char*> compressIndicesInternal(const std::vector<UnsignedInt>& indices, UnsignedInt max) { std::tuple<std::size_t, Mesh::IndexType, Containers::Array<char>> compressIndicesInternal(const std::vector<UnsignedInt>& indices, UnsignedInt max) {
switch(Math::log(256, max)) { switch(Math::log(256, max)) {
case 0: case 0:
return compress<UnsignedByte>(indices); return compress<UnsignedByte>(indices);
@ -65,7 +65,7 @@ std::tuple<std::size_t, Mesh::IndexType, char*> compressIndicesInternal(const st
} }
std::tuple<std::size_t, Mesh::IndexType, char*> compressIndices(const std::vector<UnsignedInt>& indices) { std::tuple<std::size_t, Mesh::IndexType, Containers::Array<char>> compressIndices(const std::vector<UnsignedInt>& indices) {
return compressIndicesInternal(indices, *std::max_element(indices.begin(), indices.end())); return compressIndicesInternal(indices, *std::max_element(indices.begin(), indices.end()));
} }
@ -76,14 +76,12 @@ void compressIndices(Mesh& mesh, Buffer& buffer, Buffer::Usage usage, const std:
std::size_t indexCount; std::size_t indexCount;
Mesh::IndexType indexType; Mesh::IndexType indexType;
char* data; Containers::Array<char> data;
std::tie(indexCount, indexType, data) = compressIndicesInternal(indices, *minmax.second); std::tie(indexCount, indexType, data) = compressIndicesInternal(indices, *minmax.second);
mesh.setIndexCount(indices.size()) mesh.setIndexCount(indices.size())
.setIndexBuffer(buffer, 0, indexType, *minmax.first, *minmax.second); .setIndexBuffer(buffer, 0, indexType, *minmax.first, *minmax.second);
buffer.setData({data, indexCount*Mesh::indexSize(indexType)}, usage); buffer.setData(data, usage);
delete[] data;
} }
}} }}

13
src/MeshTools/CompressIndices.h

@ -40,28 +40,23 @@ namespace Magnum { namespace MeshTools {
/** /**
@brief Compress vertex indices @brief Compress vertex indices
@param indices Index array @param indices Index array
@return Index count, type and compressed index array. Deleting the array is @return Index count, type and compressed index array
user responsibility.
This function takes index array and outputs them compressed to smallest This function takes index array and outputs them compressed to smallest
possible size. For example when your indices have maximum number 463, it's possible size. For example when your indices have maximum number 463, it's
wasteful to store them in array of 32bit integers, array of 16bit integers is wasteful to store them in array of 32bit integers, array of 16bit integers is
sufficient. Size of the buffer can be computed from index count and type, as sufficient. Example usage:
shown below. Example usage:
@code @code
std::size_t indexCount; std::size_t indexCount;
Mesh::IndexType indexType; Mesh::IndexType indexType;
char* data; Containers::Array<char> data;
std::tie(indexCount, indexType, data) = MeshTools::compressIndices(indices); std::tie(indexCount, indexType, data) = MeshTools::compressIndices(indices);
std::size_t dataSize = indexCount*Mesh::indexSize(indexType);
// ...
delete[] data;
@endcode @endcode
See also compressIndices(Mesh*, Buffer*, Buffer::Usage, const std::vector<UnsignedInt>&), See also compressIndices(Mesh*, Buffer*, Buffer::Usage, const std::vector<UnsignedInt>&),
which writes the compressed data directly into index buffer of given mesh. which writes the compressed data directly into index buffer of given mesh.
*/ */
std::tuple<std::size_t, Mesh::IndexType, char*> MAGNUM_MESHTOOLS_EXPORT compressIndices(const std::vector<UnsignedInt>& indices); std::tuple<std::size_t, Mesh::IndexType, Containers::Array<char>> MAGNUM_MESHTOOLS_EXPORT compressIndices(const std::vector<UnsignedInt>& indices);
/** /**
@brief Compress vertex indices and write them to index buffer @brief Compress vertex indices and write them to index buffer

22
src/MeshTools/Test/CompressIndicesTest.cpp

@ -47,48 +47,44 @@ CompressIndicesTest::CompressIndicesTest() {
void CompressIndicesTest::compressChar() { void CompressIndicesTest::compressChar() {
std::size_t indexCount; std::size_t indexCount;
Mesh::IndexType indexType; Mesh::IndexType indexType;
char* data; Containers::Array<char> data;
std::tie(indexCount, indexType, data) = MeshTools::compressIndices( std::tie(indexCount, indexType, data) = MeshTools::compressIndices(
std::vector<UnsignedInt>{1, 2, 3, 0, 4}); std::vector<UnsignedInt>{1, 2, 3, 0, 4});
CORRADE_COMPARE(indexCount, 5); CORRADE_COMPARE(indexCount, 5);
CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedByte); CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedByte);
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*Mesh::indexSize(indexType)), CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()),
(std::vector<char>{ 0x01, 0x02, 0x03, 0x00, 0x04 })); (std::vector<char>{ 0x01, 0x02, 0x03, 0x00, 0x04 }));
delete[] data;
} }
void CompressIndicesTest::compressShort() { void CompressIndicesTest::compressShort() {
std::size_t indexCount; std::size_t indexCount;
Mesh::IndexType indexType; Mesh::IndexType indexType;
char* data; Containers::Array<char> data;
std::tie(indexCount, indexType, data) = MeshTools::compressIndices( std::tie(indexCount, indexType, data) = MeshTools::compressIndices(
std::vector<UnsignedInt>{1, 256, 0, 5}); std::vector<UnsignedInt>{1, 256, 0, 5});
CORRADE_COMPARE(indexCount, 4); CORRADE_COMPARE(indexCount, 4);
CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedShort); CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedShort);
if(!Utility::Endianness::isBigEndian()) { if(!Utility::Endianness::isBigEndian()) {
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*Mesh::indexSize(indexType)), CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()),
(std::vector<char>{ 0x01, 0x00, (std::vector<char>{ 0x01, 0x00,
0x00, 0x01, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x05, 0x00 })); 0x05, 0x00 }));
} else { } else {
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*Mesh::indexSize(indexType)), CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()),
(std::vector<char>{ 0x00, 0x01, (std::vector<char>{ 0x00, 0x01,
0x01, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x05 })); 0x00, 0x05 }));
} }
delete[] data;
} }
void CompressIndicesTest::compressInt() { void CompressIndicesTest::compressInt() {
std::size_t indexCount; std::size_t indexCount;
Mesh::IndexType indexType; Mesh::IndexType indexType;
char* data; Containers::Array<char> data;
std::tie(indexCount, indexType, data) = MeshTools::compressIndices( std::tie(indexCount, indexType, data) = MeshTools::compressIndices(
std::vector<UnsignedInt>{65536, 3, 2}); std::vector<UnsignedInt>{65536, 3, 2});
@ -96,18 +92,16 @@ void CompressIndicesTest::compressInt() {
CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedInt); CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedInt);
if(!Utility::Endianness::isBigEndian()) { if(!Utility::Endianness::isBigEndian()) {
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*Mesh::indexSize(indexType)), CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()),
(std::vector<char>{ 0x00, 0x00, 0x01, 0x00, (std::vector<char>{ 0x00, 0x00, 0x01, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00 })); 0x02, 0x00, 0x00, 0x00 }));
} else { } else {
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*Mesh::indexSize(indexType)), CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()),
(std::vector<char>{ 0x00, 0x01, 0x00, 0x00, (std::vector<char>{ 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x02 })); 0x00, 0x00, 0x00, 0x02 }));
} }
delete[] data;
} }
}}} }}}

Loading…
Cancel
Save