From ca24fe8f4103d8ed75b844859318e18474d58726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Jan 2013 23:46:44 +0100 Subject: [PATCH] Mesh index type cleanup. Using specialized enum instead of global Type and shitload of type traits to handle it correctly. Removed TypeTraits::indexType() and cleaned up MeshTools::compressIndices() while at it. --- src/DebugTools/ObjectRenderer.cpp | 2 +- src/IndexedMesh.cpp | 10 ++++ src/IndexedMesh.h | 29 ++++++++-- src/MeshTools/CompressIndices.cpp | 63 +++++++++++++--------- src/MeshTools/CompressIndices.h | 32 ++--------- src/MeshTools/Test/CompressIndicesTest.cpp | 22 ++++---- src/TypeTraits.h | 22 +------- 7 files changed, 89 insertions(+), 91 deletions(-) diff --git a/src/DebugTools/ObjectRenderer.cpp b/src/DebugTools/ObjectRenderer.cpp index 3632f65a8..39367cc56 100644 --- a/src/DebugTools/ObjectRenderer.cpp +++ b/src/DebugTools/ObjectRenderer.cpp @@ -160,7 +160,7 @@ template ObjectRenderer::ObjectRenderer(Sce mesh->setPrimitive(Mesh::Primitive::Lines) ->addInterleavedVertexBuffer(vertexBuffer, 0, typename Shaders::VertexColorShader::Position(), typename Shaders::VertexColorShader::Color()) ->setIndexCount(Renderer::indices.size()) - ->setIndexType(Type::UnsignedByte) + ->setIndexType(IndexedMesh::IndexType::UnsignedByte) ->setIndexBuffer(indexBuffer); ResourceManager::instance()->set(this->mesh.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual); } diff --git a/src/IndexedMesh.cpp b/src/IndexedMesh.cpp index e6527bf78..8053cbfcf 100644 --- a/src/IndexedMesh.cpp +++ b/src/IndexedMesh.cpp @@ -26,6 +26,16 @@ namespace Magnum { IndexedMesh::BindIndexBufferImplementation IndexedMesh::bindIndexBufferImplementation = &IndexedMesh::bindIndexBufferImplementationDefault; IndexedMesh::BindIndexedImplementation IndexedMesh::bindIndexedImplementation = &IndexedMesh::bindIndexedImplementationDefault; +std::size_t IndexedMesh::indexSize(IndexType type) { + switch(type) { + case IndexType::UnsignedByte: return 1; + case IndexType::UnsignedShort: return 2; + case IndexType::UnsignedInt: return 4; + } + + CORRADE_INTERNAL_ASSERT(false); +} + IndexedMesh* IndexedMesh::setIndexBuffer(Buffer* buffer) { _indexBuffer = buffer; (this->*bindIndexBufferImplementation)(); diff --git a/src/IndexedMesh.h b/src/IndexedMesh.h index 80e390346..090942179 100644 --- a/src/IndexedMesh.h +++ b/src/IndexedMesh.h @@ -72,6 +72,25 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { friend class Context; public: + /** + * @brief Index type + * + * @see setIndexType(), indexSize() + */ + enum class IndexType: GLenum { + UnsignedByte = GL_UNSIGNED_BYTE, /**< Unsigned byte */ + UnsignedShort = GL_UNSIGNED_SHORT, /**< Unsigned short */ + + /** + * Unsigned int + * @requires_gles30 %Extension @es_extension{OES,element_index_uint} + */ + UnsignedInt = GL_UNSIGNED_INT + }; + + /** @brief Size of given index type */ + static std::size_t indexSize(IndexType type); + /** * @brief Constructor * @param primitive Primitive type @@ -79,7 +98,7 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { * Creates indexed mesh with zero vertex count, zero index count and * no vertex or index buffers. */ - inline explicit IndexedMesh(Primitive primitive = Primitive::Triangles): Mesh(primitive), _indexBuffer(nullptr), _indexCount(0), _indexType(Type::UnsignedShort) {} + inline explicit IndexedMesh(Primitive primitive = Primitive::Triangles): Mesh(primitive), _indexBuffer(nullptr), _indexCount(0), _indexType(IndexType::UnsignedInt) {} /** * @brief Set index buffer @@ -106,16 +125,16 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { } /** @brief Index type */ - inline Type indexType() const { return _indexType; } + inline IndexType indexType() const { return _indexType; } /** * @brief Set index type * @return Pointer to self (for method chaining) * - * Default is @ref Type "Type::UnsignedShort". + * Default is @ref Type "IndexType::UnsignedInt". * @see setIndexBuffer(), setIndexCount(), MeshTools::compressIndices() */ - inline IndexedMesh* setIndexType(Type type) { + inline IndexedMesh* setIndexType(IndexType type) { _indexType = type; return this; } @@ -174,7 +193,7 @@ class MAGNUM_EXPORT IndexedMesh: public Mesh { Buffer* _indexBuffer; GLsizei _indexCount; - Type _indexType; + IndexType _indexType; }; } diff --git a/src/MeshTools/CompressIndices.cpp b/src/MeshTools/CompressIndices.cpp index af2a53e93..0ca368fbb 100644 --- a/src/MeshTools/CompressIndices.cpp +++ b/src/MeshTools/CompressIndices.cpp @@ -16,47 +16,62 @@ #include "CompressIndices.h" #include -#include #include -#include "IndexedMesh.h" -#include "SizeTraits.h" +#include "Math/Math.h" namespace Magnum { namespace MeshTools { #ifndef DOXYGEN_GENERATING_OUTPUT -namespace Implementation { +namespace { -std::tuple CompressIndices::operator()() const { - return SizeBasedCall(*std::max_element(indices.begin(), indices.end()))(indices); +template constexpr IndexedMesh::IndexType indexType(); +template<> inline constexpr IndexedMesh::IndexType indexType() { return IndexedMesh::IndexType::UnsignedByte; } +template<> inline constexpr IndexedMesh::IndexType indexType() { return IndexedMesh::IndexType::UnsignedShort; } +template<> inline constexpr IndexedMesh::IndexType indexType() { return IndexedMesh::IndexType::UnsignedInt; } + +template inline std::tuple compress(const std::vector& indices) { + char* buffer = new char[indices.size()*sizeof(T)]; + for(std::size_t i = 0; i != indices.size(); ++i) { + T index = static_cast(indices[i]); + std::memcpy(buffer+i*sizeof(T), &index, sizeof(T)); + } + + return std::make_tuple(indices.size(), indexType(), buffer); +} + +} +#endif + +std::tuple compressIndices(const std::vector& indices) { + std::size_t size = *std::max_element(indices.begin(), indices.end()); + + switch(Math::log(256, size)) { + case 0: + return compress(indices); + case 1: + return compress(indices); + case 2: + case 3: + return compress(indices); + + default: + CORRADE_ASSERT(false, "MeshTools::compressIndices(): no type able to index" << size << "elements.", {}); + } } -void CompressIndices::operator()(IndexedMesh* mesh, Buffer* buffer, Buffer::Usage usage) const { +void compressIndices(IndexedMesh* mesh, Buffer* buffer, Buffer::Usage usage, const std::vector& indices) { std::size_t indexCount; - Type indexType; + IndexedMesh::IndexType indexType; char* data; - std::tie(indexCount, indexType, data) = operator()(); + std::tie(indexCount, indexType, data) = compressIndices(indices); mesh->setIndexBuffer(buffer) ->setIndexType(indexType) ->setIndexCount(indices.size()); - buffer->setData(indexCount*TypeInfo::sizeOf(indexType), data, usage); + buffer->setData(indexCount*IndexedMesh::indexSize(indexType), data, usage); delete[] data; } -template std::tuple CompressIndices::Compressor::run(const std::vector& indices) { - /* Create smallest possible version of index buffer */ - char* buffer = new char[indices.size()*sizeof(IndexType)]; - for(std::size_t i = 0; i != indices.size(); ++i) { - IndexType index = indices[i]; - memcpy(buffer+i*sizeof(IndexType), reinterpret_cast(&index), sizeof(IndexType)); - } - - return std::make_tuple(indices.size(), TypeTraits::indexType(), buffer); -} - -} -#endif - }} diff --git a/src/MeshTools/CompressIndices.h b/src/MeshTools/CompressIndices.h index 34ccb7991..120e1bb04 100644 --- a/src/MeshTools/CompressIndices.h +++ b/src/MeshTools/CompressIndices.h @@ -22,34 +22,12 @@ #include #include "Buffer.h" -#include "TypeTraits.h" +#include "IndexedMesh.h" #include "magnumMeshToolsVisibility.h" namespace Magnum { namespace MeshTools { -#ifndef DOXYGEN_GENERATING_OUTPUT -namespace Implementation { - -class MAGNUM_MESHTOOLS_EXPORT CompressIndices { - public: - CompressIndices(const std::vector& indices): indices(indices) {} - - std::tuple operator()() const; - - void operator()(IndexedMesh* mesh, Buffer* buffer, Buffer::Usage usage) const; - - private: - struct Compressor { - template static std::tuple run(const std::vector& indices); - }; - - const std::vector& indices; -}; - -} -#endif - /** @brief Compress vertex indices @param indices Index array @@ -74,9 +52,7 @@ delete[] data; See also compressIndices(IndexedMesh*, Buffer::Usage, const std::vector&), which writes the compressed data directly into index buffer of given mesh. */ -inline std::tuple compressIndices(const std::vector& indices) { - return Implementation::CompressIndices{indices}(); -} +std::tuple MAGNUM_MESHTOOLS_EXPORT compressIndices(const std::vector& indices); /** @brief Compress vertex indices and write them to index buffer @@ -93,9 +69,7 @@ IndexedMesh::setIndexType() on your own. @see MeshTools::interleave() */ -inline void compressIndices(IndexedMesh* mesh, Buffer* buffer, Buffer::Usage usage, const std::vector& indices) { - return Implementation::CompressIndices{indices}(mesh, buffer, usage); -} +void MAGNUM_MESHTOOLS_EXPORT compressIndices(IndexedMesh* mesh, Buffer* buffer, Buffer::Usage usage, const std::vector& indices); }} diff --git a/src/MeshTools/Test/CompressIndicesTest.cpp b/src/MeshTools/Test/CompressIndicesTest.cpp index 696e949fb..56731f2c1 100644 --- a/src/MeshTools/Test/CompressIndicesTest.cpp +++ b/src/MeshTools/Test/CompressIndicesTest.cpp @@ -39,14 +39,14 @@ CompressIndicesTest::CompressIndicesTest() { void CompressIndicesTest::compressChar() { std::size_t indexCount; - Type indexType; + IndexedMesh::IndexType indexType; char* data; std::tie(indexCount, indexType, data) = MeshTools::compressIndices( std::vector{1, 2, 3, 0, 4}); CORRADE_COMPARE(indexCount, 5); - CORRADE_VERIFY(indexType == Type::UnsignedByte); - CORRADE_COMPARE(std::vector(data, data+indexCount*TypeInfo::sizeOf(indexType)), + CORRADE_VERIFY(indexType == IndexedMesh::IndexType::UnsignedByte); + CORRADE_COMPARE(std::vector(data, data+indexCount*IndexedMesh::indexSize(indexType)), (std::vector{ 0x01, 0x02, 0x03, 0x00, 0x04 })); delete[] data; @@ -54,21 +54,21 @@ void CompressIndicesTest::compressChar() { void CompressIndicesTest::compressShort() { std::size_t indexCount; - Type indexType; + IndexedMesh::IndexType indexType; char* data; std::tie(indexCount, indexType, data) = MeshTools::compressIndices( std::vector{1, 256, 0, 5}); CORRADE_COMPARE(indexCount, 4); - CORRADE_VERIFY(indexType == Type::UnsignedShort); + CORRADE_VERIFY(indexType == IndexedMesh::IndexType::UnsignedShort); if(!Endianness::isBigEndian()) { - CORRADE_COMPARE(std::vector(data, data+indexCount*TypeInfo::sizeOf(indexType)), + CORRADE_COMPARE(std::vector(data, data+indexCount*IndexedMesh::indexSize(indexType)), (std::vector{ 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00 })); } else { - CORRADE_COMPARE(std::vector(data, data+indexCount*TypeInfo::sizeOf(indexType)), + CORRADE_COMPARE(std::vector(data, data+indexCount*IndexedMesh::indexSize(indexType)), (std::vector{ 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, @@ -80,21 +80,21 @@ void CompressIndicesTest::compressShort() { void CompressIndicesTest::compressInt() { std::size_t indexCount; - Type indexType; + IndexedMesh::IndexType indexType; char* data; std::tie(indexCount, indexType, data) = MeshTools::compressIndices( std::vector{65536, 3, 2}); CORRADE_COMPARE(indexCount, 3); - CORRADE_VERIFY(indexType == Type::UnsignedInt); + CORRADE_VERIFY(indexType == IndexedMesh::IndexType::UnsignedInt); if(!Endianness::isBigEndian()) { - CORRADE_COMPARE(std::vector(data, data+indexCount*TypeInfo::sizeOf(indexType)), + CORRADE_COMPARE(std::vector(data, data+indexCount*IndexedMesh::indexSize(indexType)), (std::vector{ 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 })); } else { - CORRADE_COMPARE(std::vector(data, data+indexCount*TypeInfo::sizeOf(indexType)), + CORRADE_COMPARE(std::vector(data, data+indexCount*IndexedMesh::indexSize(indexType)), (std::vector{ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02 })); diff --git a/src/TypeTraits.h b/src/TypeTraits.h index 9366bd872..8c096feeb 100644 --- a/src/TypeTraits.h +++ b/src/TypeTraits.h @@ -61,15 +61,6 @@ template struct TypeTraits: Math::MathTypeTraits { */ inline constexpr static Type type(); - /** - * @brief OpenGL type ID for indices - * - * Implemented only in types which can be used for vertex indices (all - * unsigned types). This function is not present for types unusable for - * vertex indices, like GLfloat or GLint. - */ - inline constexpr static Type indexType(); - /** * @brief Size of plain OpenGL type * @@ -204,7 +195,6 @@ template<> struct TypeOf { template<> struct TypeTraits: Math::MathTypeTraits { /* Can not be used for attributes */ inline constexpr static Type type() { return Type::UnsignedByte; } - inline constexpr static Type indexType() { return Type::UnsignedByte; } inline constexpr static std::size_t size() { return sizeof(GLubyte); } inline constexpr static std::size_t count() { return 1; } }; @@ -212,7 +202,6 @@ template<> struct TypeTraits: Math::MathTypeTraits { template<> struct TypeTraits: Math::MathTypeTraits { /* Can not be used for attributes */ inline constexpr static Type type() { return Type::Byte; } - /* Can not be used for indices */ inline constexpr static std::size_t size() { return sizeof(GLbyte); } inline constexpr static std::size_t count() { return 1; } }; @@ -220,7 +209,6 @@ template<> struct TypeTraits: Math::MathTypeTraits { template<> struct TypeTraits: Math::MathTypeTraits { /* Can not be used for attributes */ inline constexpr static Type type() { return Type::UnsignedShort; } - inline constexpr static Type indexType() { return Type::UnsignedShort; } inline constexpr static std::size_t size() { return sizeof(GLushort); } inline constexpr static std::size_t count() { return 1; } }; @@ -228,7 +216,6 @@ template<> struct TypeTraits: Math::MathTypeTraits { template<> struct TypeTraits: Math::MathTypeTraits { /* Can not be used for attributes */ inline constexpr static Type type() { return Type::Short; } - /* Can not be used for indices */ inline constexpr static std::size_t size() { return sizeof(GLshort); } inline constexpr static std::size_t count() { return 1; } }; @@ -236,7 +223,6 @@ template<> struct TypeTraits: Math::MathTypeTraits { template<> struct TypeTraits: Math::MathTypeTraits { typedef GLuint AttributeType; inline constexpr static Type type() { return Type::UnsignedInt; } - inline constexpr static Type indexType() { return Type::UnsignedInt; } inline constexpr static std::size_t size() { return sizeof(GLuint); } inline constexpr static std::size_t count() { return 1; } }; @@ -244,7 +230,6 @@ template<> struct TypeTraits: Math::MathTypeTraits { template<> struct TypeTraits: Math::MathTypeTraits { typedef GLint AttributeType; inline constexpr static Type type() { return Type::Int; } - /* Can not be used for indices */ inline constexpr static std::size_t size() { return sizeof(GLint); } inline constexpr static std::size_t count() { return 1; } }; @@ -252,7 +237,6 @@ template<> struct TypeTraits: Math::MathTypeTraits { template<> struct TypeTraits: Math::MathTypeTraits { typedef GLfloat AttributeType; inline constexpr static Type type() { return Type::Float; } - /* Can not be used for indices */ inline constexpr static std::size_t size() { return sizeof(GLfloat); } inline constexpr static std::size_t count() { return 1; } }; @@ -261,7 +245,6 @@ template<> struct TypeTraits: Math::MathTypeTraits { template<> struct TypeTraits: Math::MathTypeTraits { typedef GLdouble AttributeType; inline constexpr static Type type() { return Type::Double; } - /* Can not be used for indices */ inline constexpr static std::size_t size() { return sizeof(GLdouble); } inline constexpr static std::size_t count() { return 1; } }; @@ -273,8 +256,6 @@ namespace Implementation { /* Might be used for attributes, see below */ inline constexpr static Type type() { return TypeTraits::type(); } - /* Might be used for attributes, see below */ - /* Can not be used for indices */ inline constexpr static std::size_t size() { return sizeof(T); } inline constexpr static std::size_t count() { return vectorSize; } }; @@ -320,9 +301,8 @@ namespace Implementation { template struct MatrixTypeTraits { MatrixTypeTraits() = delete; - inline constexpr static Type type() { return TypeTraits::type(); } /* Might be used for attributes, see below */ - /* Can not be used for indices */ + inline constexpr static Type type() { return TypeTraits::type(); } inline constexpr static std::size_t size() { return sizeof(T); } inline constexpr static std::size_t count() { return rows; } inline constexpr static std::size_t vectors() { return cols; }