Browse Source

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.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
ca24fe8f41
  1. 2
      src/DebugTools/ObjectRenderer.cpp
  2. 10
      src/IndexedMesh.cpp
  3. 29
      src/IndexedMesh.h
  4. 63
      src/MeshTools/CompressIndices.cpp
  5. 32
      src/MeshTools/CompressIndices.h
  6. 22
      src/MeshTools/Test/CompressIndicesTest.cpp
  7. 22
      src/TypeTraits.h

2
src/DebugTools/ObjectRenderer.cpp

@ -160,7 +160,7 @@ template<std::uint8_t dimensions> ObjectRenderer<dimensions>::ObjectRenderer(Sce
mesh->setPrimitive(Mesh::Primitive::Lines)
->addInterleavedVertexBuffer(vertexBuffer, 0, typename Shaders::VertexColorShader<dimensions>::Position(), typename Shaders::VertexColorShader<dimensions>::Color())
->setIndexCount(Renderer<dimensions>::indices.size())
->setIndexType(Type::UnsignedByte)
->setIndexType(IndexedMesh::IndexType::UnsignedByte)
->setIndexBuffer(indexBuffer);
ResourceManager::instance()->set<Mesh>(this->mesh.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual);
}

10
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)();

29
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;
};
}

63
src/MeshTools/CompressIndices.cpp

@ -16,47 +16,62 @@
#include "CompressIndices.h"
#include <cstring>
#include <vector>
#include <algorithm>
#include "IndexedMesh.h"
#include "SizeTraits.h"
#include "Math/Math.h"
namespace Magnum { namespace MeshTools {
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
namespace {
std::tuple<std::size_t, Type, char* > CompressIndices::operator()() const {
return SizeBasedCall<Compressor>(*std::max_element(indices.begin(), indices.end()))(indices);
template<class> constexpr IndexedMesh::IndexType indexType();
template<> inline constexpr IndexedMesh::IndexType indexType<GLubyte>() { return IndexedMesh::IndexType::UnsignedByte; }
template<> inline constexpr IndexedMesh::IndexType indexType<GLushort>() { return IndexedMesh::IndexType::UnsignedShort; }
template<> inline constexpr IndexedMesh::IndexType indexType<GLuint>() { return IndexedMesh::IndexType::UnsignedInt; }
template<class T> inline std::tuple<std::size_t, IndexedMesh::IndexType, char*> compress(const std::vector<std::uint32_t>& indices) {
char* buffer = new char[indices.size()*sizeof(T)];
for(std::size_t i = 0; i != indices.size(); ++i) {
T index = static_cast<T>(indices[i]);
std::memcpy(buffer+i*sizeof(T), &index, sizeof(T));
}
return std::make_tuple(indices.size(), indexType<T>(), buffer);
}
}
#endif
std::tuple<std::size_t, IndexedMesh::IndexType, char*> compressIndices(const std::vector<std::uint32_t>& indices) {
std::size_t size = *std::max_element(indices.begin(), indices.end());
switch(Math::log(256, size)) {
case 0:
return compress<GLubyte>(indices);
case 1:
return compress<GLushort>(indices);
case 2:
case 3:
return compress<GLuint>(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<std::uint32_t>& 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<class IndexType> std::tuple<std::size_t, Type, char*> CompressIndices::Compressor::run(const std::vector<std::uint32_t>& 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<const char*>(&index), sizeof(IndexType));
}
return std::make_tuple(indices.size(), TypeTraits<IndexType>::indexType(), buffer);
}
}
#endif
}}

32
src/MeshTools/CompressIndices.h

@ -22,34 +22,12 @@
#include <tuple>
#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<std::uint32_t>& indices): indices(indices) {}
std::tuple<std::size_t, Type, char*> operator()() const;
void operator()(IndexedMesh* mesh, Buffer* buffer, Buffer::Usage usage) const;
private:
struct Compressor {
template<class IndexType> static std::tuple<std::size_t, Type, char*> run(const std::vector<std::uint32_t>& indices);
};
const std::vector<std::uint32_t>& 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<std::uint32_t>&),
which writes the compressed data directly into index buffer of given mesh.
*/
inline std::tuple<std::size_t, Type, char*> compressIndices(const std::vector<std::uint32_t>& indices) {
return Implementation::CompressIndices{indices}();
}
std::tuple<std::size_t, IndexedMesh::IndexType, char*> MAGNUM_MESHTOOLS_EXPORT compressIndices(const std::vector<std::uint32_t>& 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<std::uint32_t>& indices) {
return Implementation::CompressIndices{indices}(mesh, buffer, usage);
}
void MAGNUM_MESHTOOLS_EXPORT compressIndices(IndexedMesh* mesh, Buffer* buffer, Buffer::Usage usage, const std::vector<std::uint32_t>& indices);
}}

22
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<std::uint32_t>{1, 2, 3, 0, 4});
CORRADE_COMPARE(indexCount, 5);
CORRADE_VERIFY(indexType == Type::UnsignedByte);
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*TypeInfo::sizeOf(indexType)),
CORRADE_VERIFY(indexType == IndexedMesh::IndexType::UnsignedByte);
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*IndexedMesh::indexSize(indexType)),
(std::vector<char>{ 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<std::uint32_t>{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<char>(data, data+indexCount*TypeInfo::sizeOf(indexType)),
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*IndexedMesh::indexSize(indexType)),
(std::vector<char>{ 0x01, 0x00,
0x00, 0x01,
0x00, 0x00,
0x05, 0x00 }));
} else {
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*TypeInfo::sizeOf(indexType)),
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*IndexedMesh::indexSize(indexType)),
(std::vector<char>{ 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<std::uint32_t>{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<char>(data, data+indexCount*TypeInfo::sizeOf(indexType)),
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*IndexedMesh::indexSize(indexType)),
(std::vector<char>{ 0x00, 0x00, 0x01, 0x00,
0x03, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00 }));
} else {
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*TypeInfo::sizeOf(indexType)),
CORRADE_COMPARE(std::vector<char>(data, data+indexCount*IndexedMesh::indexSize(indexType)),
(std::vector<char>{ 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x02 }));

22
src/TypeTraits.h

@ -61,15 +61,6 @@ template<class T> struct TypeTraits: Math::MathTypeTraits<T> {
*/
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<Type::Double> {
template<> struct TypeTraits<GLubyte>: Math::MathTypeTraits<std::uint8_t> {
/* 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<GLubyte>: Math::MathTypeTraits<std::uint8_t> {
template<> struct TypeTraits<GLbyte>: Math::MathTypeTraits<std::int8_t> {
/* 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<GLbyte>: Math::MathTypeTraits<std::int8_t> {
template<> struct TypeTraits<GLushort>: Math::MathTypeTraits<std::uint16_t> {
/* 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<GLushort>: Math::MathTypeTraits<std::uint16_t> {
template<> struct TypeTraits<GLshort>: Math::MathTypeTraits<std::int16_t> {
/* 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<GLshort>: Math::MathTypeTraits<std::int16_t> {
template<> struct TypeTraits<GLuint>: Math::MathTypeTraits<std::uint32_t> {
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<GLuint>: Math::MathTypeTraits<std::uint32_t> {
template<> struct TypeTraits<GLint>: Math::MathTypeTraits<std::int32_t> {
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<GLint>: Math::MathTypeTraits<std::int32_t> {
template<> struct TypeTraits<GLfloat>: Math::MathTypeTraits<float> {
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<GLfloat>: Math::MathTypeTraits<float> {
template<> struct TypeTraits<GLdouble>: Math::MathTypeTraits<double> {
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<T>::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<std::size_t cols, std::size_t rows, class T> struct MatrixTypeTraits {
MatrixTypeTraits() = delete;
inline constexpr static Type type() { return TypeTraits<T>::type(); }
/* Might be used for attributes, see below */
/* Can not be used for indices */
inline constexpr static Type type() { return TypeTraits<T>::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; }

Loading…
Cancel
Save