Browse Source

Hiding MeshTools implementation classes from user altogether.

All classes moved to MeshTools::Implementation namespace and removed
from Doxygen output. They now all return tuples instead of custom
structures. Updated and improved documentation, removed references to
implementation classes.
vectorfields
Vladimír Vondruš 14 years ago
parent
commit
91c2b5e389
  1. 38
      src/MeshTools/Clean.h
  2. 102
      src/MeshTools/CompressIndices.h
  3. 138
      src/MeshTools/Interleave.h
  4. 36
      src/MeshTools/Subdivide.h
  5. 43
      src/MeshTools/Test/CompressIndicesTest.cpp
  6. 29
      src/MeshTools/Test/InterleaveTest.cpp
  7. 2
      src/MeshTools/Test/TipsifyTest.cpp
  8. 6
      src/MeshTools/Tipsify.cpp
  9. 33
      src/MeshTools/Tipsify.h

38
src/MeshTools/Clean.h

@ -16,7 +16,7 @@
*/
/** @file
* @brief Class Magnum::MeshTools::Clean, function Magnum::MeshTools::clean()
* @brief Function Magnum::MeshTools::clean()
*/
#include <unordered_map>
@ -27,25 +27,13 @@
namespace Magnum { namespace MeshTools {
/**
@brief %Mesh cleaner implementation
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
See clean() for full documentation.
*/
template<class Vertex, size_t vertexSize = Vertex::Size> class Clean {
public:
/**
* @brief Constructor
*
* See clean() for full documentation.
*/
inline Clean(std::vector<unsigned int>& indices, std::vector<Vertex>& vertices): indices(indices), vertices(vertices) {}
/**
* @brief Functor
*
* See clean() for full documentation.
*/
void operator()(typename Vertex::Type epsilon = TypeTraits<typename Vertex::Type>::epsilon()) {
if(indices.empty()) return;
@ -128,6 +116,9 @@ template<class Vertex, size_t vertexSize = Vertex::Size> class Clean {
std::vector<Vertex>& vertices;
};
}
#endif
/**
@brief %Clean the mesh
@tparam Vertex Vertex data type
@ -140,24 +131,9 @@ template<class Vertex, size_t vertexSize = Vertex::Size> class Clean {
melt together.
Removes duplicate vertices from the mesh.
This is convenience function supplementing direct usage of Clean class,
instead of
@code
MeshTools::Clean<T>(indices, vertices)(epsilon);
@endcode
you can just write
@code
MeshTools::clean(indices, vertices, epsilon);
@endcode
However, when you want to specify `vertexSize` template parameter, you have
to explicitly specify both of them:
@code
MeshTools::clean<T, 3>(indices, vertices, epsilon);
@endcode
*/
template<class Vertex, size_t vertexSize = Vertex::Size> inline void clean(std::vector<unsigned int>& indices, std::vector<Vertex>& vertices, typename Vertex::Type epsilon = TypeTraits<typename Vertex::Type>::epsilon()) {
Clean<Vertex, vertexSize>(indices, vertices)(epsilon);
Implementation::Clean<Vertex, vertexSize>(indices, vertices)(epsilon);
}
}}

102
src/MeshTools/CompressIndices.h

@ -16,7 +16,7 @@
*/
/** @file
* @brief Class Magnum::MeshTools::CompressIndices, function Magnum::MeshTools::compressIndices()
* @brief Function Magnum::MeshTools::compressIndices()
*/
#include <cstring>
@ -29,64 +29,33 @@
namespace Magnum { namespace MeshTools {
/**
@brief Index compressor implementation
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
See compressIndices() for full documentation.
*/
class CompressIndices {
public:
/**
* @brief Compressed index array
*
* Size of the data buffer can be computed as follows:
* @code
* Result result;
* size_t size = result.indexCount*TypeInfo::sizeOf(result.indexType);
* @endcode
*/
struct Result {
size_t indexCount; /**< @brief Index count */
Type indexType; /**< @brief Index data type */
char* data; /**< @brief Data buffer */
};
/**
* @brief Constructor
*
* See compressIndices() for full documentation.
*/
CompressIndices(const std::vector<unsigned int>& indices): indices(indices) {}
/**
* @brief Functor
*
* See compressIndices(const std::vector<unsigned int>&) for full
* documentation.
*/
inline Result operator()() const {
inline std::tuple<size_t, Type, char*> operator()() const {
return SizeBasedCall<Compressor>(*std::max_element(indices.begin(), indices.end()))(indices);
}
/**
* @brief Functor
*
* See compressIndices(IndexedMesh*, Buffer::Usage, const
* std::vector<unsigned int>&) for full documentation.
*/
void operator()(IndexedMesh* mesh, Buffer::Usage usage) const {
Result compressed = operator()();
size_t indexCount;
Type indexType;
char* data;
std::tie(indexCount, indexType, data) = operator()();
mesh->setIndexType(compressed.indexType);
mesh->setIndexType(indexType);
mesh->setIndexCount(indices.size());
mesh->indexBuffer()->setData(compressed.indexCount*TypeInfo::sizeOf(compressed.indexType), compressed.data, usage);
mesh->indexBuffer()->setData(indexCount*TypeInfo::sizeOf(indexType), data, usage);
delete[] compressed.data;
delete[] data;
}
private:
struct Compressor {
template<class IndexType> static Result run(const std::vector<unsigned int>& indices) {
template<class IndexType> static std::tuple<size_t, Type, char*> run(const std::vector<unsigned int>& indices) {
/* Create smallest possible version of index buffer */
char* buffer = new char[indices.size()*sizeof(IndexType)];
for(size_t i = 0; i != indices.size(); ++i) {
@ -94,35 +63,42 @@ class CompressIndices {
memcpy(buffer+i*sizeof(IndexType), reinterpret_cast<const char*>(&index), sizeof(IndexType));
}
return Result{indices.size(), TypeTraits<IndexType>::indexType(), buffer};
return std::make_tuple(indices.size(), TypeTraits<IndexType>::indexType(), buffer);
}
};
const std::vector<unsigned int>& indices;
};
}
#endif
/**
@brief Compress vertex indices
@param indices Index array
@return Compressed index array. Deleting the buffer is user's responsibility.
@return Index count, type and compressed index array. Deleting the array is
user responsibility.
This function takes index array and outputs them compressed to smallest
possible size. For example when your indices have maximum number 463, it's
wasteful to store them in array of `unsigned int`s, array of
`unsigned short`s is sufficient.
This is convenience function supplementing direct usage of CompressIndices
class, instead of
wasteful to store them in array of `unsigned int`s, array of `unsigned short`s
is sufficient. Size of the buffer can be computed from index count and type,
as shown below. Example usage:
@code
MeshTools::CompressIndices{indices}();
@endcode
you can just write
@code
MeshTools::compressIndices(indices);
size_t indexCount;
Type indexType;
char* data;
std::tie(indexCount, indexType, data) = MeshTools::compressIndices(indices);
size_t dataSize = indexCount*TypeInfo::sizeOf(indexType);
// ...
delete[] data;
@endcode
See also compressIndices(IndexedMesh*, Buffer::Usage, const std::vector<unsigned int>&),
which writes the compressed data directly into index buffer of given mesh.
*/
inline CompressIndices::Result compressIndices(const std::vector<unsigned int>& indices) {
return CompressIndices{indices}();
inline std::tuple<size_t, Type, char*> compressIndices(const std::vector<unsigned int>& indices) {
return Implementation::CompressIndices{indices}();
}
/**
@ -134,19 +110,9 @@ inline CompressIndices::Result compressIndices(const std::vector<unsigned int>&
The same as compressIndices(const std::vector<unsigned int>&), but this
function writes the output to mesh's index buffer and updates index count and
type in the mesh accordingly.
This is convenience function supplementing direct usage of CompressIndices
class, instead of
@code
MeshTools::CompressIndices{indices}(mesh, usage);
@endcode
you can just write
@code
MeshTools::compressIndices(mesh, usage, indices);
@endcode
*/
inline void compressIndices(IndexedMesh* mesh, Buffer::Usage usage, const std::vector<unsigned int>& indices) {
return CompressIndices{indices}(mesh, usage);
return Implementation::CompressIndices{indices}(mesh, usage);
}
}}

138
src/MeshTools/Interleave.h

@ -16,110 +16,77 @@
*/
/** @file
* @brief Class Magnum::MeshTools::Interleave, function Magnum::MeshTools::interleave()
* @brief Function Magnum::MeshTools::interleave()
*/
#include <cassert>
#include <cstring>
#include <vector>
#include <limits>
#include <tuple>
#include "Mesh.h"
#include "Buffer.h"
namespace Magnum { namespace MeshTools {
/**
@brief Vertex attribute interleaver implementation
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
See interleave() for full documentation.
*/
class Interleave {
public:
/**
* @brief Interleaved attribute array
*
* Size of the data buffer can be computed as follows:
* @code
* Result result;
* size_t size = result.attributeCount*result.stride;
* @endcode
*/
struct Result {
size_t attributeCount; /**< @brief Attribute count */
size_t stride; /**< @brief Distance between two attributes in resulting array */
char* data; /**< @brief Data buffer */
};
/** @brief Constructor */
#ifndef DOXYGEN_GENERATING_OUTPUT
inline Interleave(): result{0, 0, 0} {}
#else
inline Interleave() {}
#endif
/**
* @brief Functor
*
* See interleave(const std::vector<T>&...) for full documentation.
*/
template<class ...T> Result operator()(const std::vector<T>&... attributes) {
inline Interleave(): _attributeCount(0), _stride(0), _data(nullptr) {}
template<class ...T> std::tuple<size_t, size_t, char*> operator()(const std::vector<T>&... attributes) {
/* Compute buffer size and stride */
result.attributeCount = attributeCount(attributes...);
if(result.attributeCount) {
result.stride = stride(attributes...);
_attributeCount = attributeCount(attributes...);
if(_attributeCount) {
_stride = stride(attributes...);
/* Create output buffer */
result.data = new char[result.attributeCount*result.stride];
_data = new char[_attributeCount*_stride];
/* Save the data */
write(result.data, attributes...);
write(_data, attributes...);
}
return result;
return std::make_tuple(_attributeCount, _stride, _data);
}
/**
* @brief Functor
*
* See interleave(Mesh*, Buffer*, Buffer::Usage, const std::vector<T>&...) for full documentation.
*/
template<class ...T> void operator()(Mesh* mesh, Buffer* buffer, Buffer::Usage usage, const std::vector<T>&... attributes) {
if(!mesh->isInterleaved(buffer)) {
Corrade::Utility::Error() << "MeshTools::Interleave: the buffer is not interleaved, nothing done";
Corrade::Utility::Error() << "MeshTools::interleave(): the buffer is not interleaved, nothing done";
assert(0);
return;
}
operator()(attributes...);
mesh->setVertexCount(result.attributeCount);
buffer->setData(result.attributeCount*result.stride, result.data, usage);
mesh->setVertexCount(_attributeCount);
buffer->setData(_attributeCount*_stride, _data, usage);
delete[] result.data;
delete[] _data;
}
/** @brief Count of passed attributes */
template<class T, class ...U> inline static size_t attributeCount(const std::vector<T>& first, const std::vector<U>&... next) {
size_t count = attributeCount(next...);
if(sizeof...(next) != 0 && count != first.size()) {
Corrade::Utility::Error() << "MeshTools::Interleave: attribute arrays don't have the same length, nothing done.";
Corrade::Utility::Error() << "MeshTools::interleave(): attribute arrays don't have the same length, nothing done.";
assert(0);
return 0;
}
return first.size();
}
/** @brief Distance between two attributes in resulting array */
template<class T, class ...U> inline static size_t stride(const std::vector<T>& first, const std::vector<U>&... next) {
return sizeof(T) + stride(next...);
}
private:
template<class T, class ...U> void write(char* startingOffset, const std::vector<T>& first, const std::vector<U>&... next) const {
template<class T, class ...U> void write(char* startingOffset, const std::vector<T>& first, const std::vector<U>&... next) {
/* Copy the data to the buffer */
for(size_t i = 0; i != result.attributeCount; ++i)
memcpy(startingOffset+i*result.stride, reinterpret_cast<const char*>(&first[i]), sizeof(T));
for(size_t i = 0; i != _attributeCount; ++i)
memcpy(startingOffset+i*_stride, reinterpret_cast<const char*>(&first[i]), sizeof(T));
write(startingOffset+sizeof(T), next...);
}
@ -127,35 +94,44 @@ class Interleave {
/* Terminator functions for recursive calls */
inline static size_t attributeCount() { return 0; }
inline static size_t stride() { return 0; }
inline void write(char*) const {}
inline void write(char*) {}
Result result;
size_t _attributeCount;
size_t _stride;
char* _data;
};
}
#endif
/**
@brief %Interleave vertex attributes
@param attributes Attribute arrays
@return Interleaved attribute array. Deleting the buffer is user's
responsibility.
This function takes two or more attribute arrays and interleaves them, so data
for each attribute are in continuous place in memory.
@return Attribute count, stride and interleaved attribute array. Deleting the
array is user responsibility.
@attention Each vector should have the same size, if not, resulting array has
zero length.
This is convenience function supplementing direct usage of Interleave class,
instead of
This function takes two or more attribute arrays and returns them interleaved,
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
MeshTools::Interleave()(attributes...);
@endcode
you can just write
@code
MeshTools::interleave(attributes...);
size_t attributeCount;
size_t stride;
char* data;
std::tie(attributeCount, stride, data) = MeshTools::interleave(attributes);
size_t dataSize = attributeCount*stride;
// ...
delete[] data;
@endcode
See also interleave(Mesh*, Buffer*, Buffer::Usage, const std::vector<T>&...),
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.
*/
template<class ...T> inline Interleave::Result interleave(const std::vector<T>&... attributes) {
return Interleave()(attributes...);
template<class ...T> inline std::tuple<size_t, size_t, char*> interleave(const std::vector<T>&... attributes) {
return Implementation::Interleave()(attributes...);
}
/**
@ -170,21 +146,11 @@ 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.
This is convenience function supplementing direct usage of Interleave class,
instead of
@code
MeshTools::Interleave()(mesh, buffer, usage, attributes...);
@endcode
you can just write
@code
MeshTools::interleave(mesh, buffer, usage, attributes...);
@endcode
otherwise this function does nothing. Binding the attributes to shader is
left to user.
*/
template<class ...T> inline void interleave(Mesh* mesh, Buffer* buffer, Buffer::Usage usage, const std::vector<T>&... attributes) {
return Interleave()(mesh, buffer, usage, attributes...);
return Implementation::Interleave()(mesh, buffer, usage, attributes...);
}
}}

36
src/MeshTools/Subdivide.h

@ -16,32 +16,21 @@
*/
/** @file
* @brief Class Magnum::MeshTools::Subdivide, function Magnum::MeshTools::subdivide()
* @brief Function Magnum::MeshTools::subdivide()
*/
#include <vector>
#include "Utility/Debug.h"
namespace Magnum { namespace MeshTools {
/**
@brief %Mesh subdivisor implementation
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
See subdivide() for full documentation.
*/
template<class Vertex, class Interpolator> class Subdivide {
public:
/**
* @brief Constructor
*
* See subdivide() for full documentation.
*/
inline Subdivide(std::vector<unsigned int>& indices, std::vector<Vertex>& vertices): indices(indices), vertices(vertices) {}
/**
* @brief Functor
*
* See subdivide() for full documentation.
*/
void operator()(Interpolator interpolator) {
size_t indexCount = indices.size();
indices.reserve(indices.size()*4);
@ -90,9 +79,12 @@ template<class Vertex, class Interpolator> class Subdivide {
}
};
}
#endif
/**
@brief %Subdivide the mesh
@tparam Vertex Vertex data type (the same as in MeshBuilder)
@tparam Vertex Vertex data type
@tparam Interpolator See `interpolator` function parameter
@param indices Index array to operate on
@param vertices Vertex array to operate on
@ -101,19 +93,9 @@ template<class Vertex, class Interpolator> class Subdivide {
Goes through all triangle faces and subdivides them into four new. Cleaning
duplicate vertices in the mesh is up to user.
This is convenience function supplementing direct usage of Subdivide class,
instead of
@code
MeshTools::Subdivide<T, Interpolator>(indices, vertices)(interpolator);
@endcode
you can just write
@code
MeshTools::subdivide(indices, vertices, interpolator);
@endcode
*/
template<class Vertex, class Interpolator> inline void subdivide(std::vector<unsigned int>& indices, std::vector<Vertex>& vertices, Interpolator interpolator) {
Subdivide<Vertex, Interpolator>(indices, vertices)(interpolator);
Implementation::Subdivide<Vertex, Interpolator>(indices, vertices)(interpolator);
}
}}

43
src/MeshTools/Test/CompressIndicesTest.cpp

@ -28,62 +28,71 @@ using namespace Corrade::Utility;
namespace Magnum { namespace MeshTools { namespace Test {
void CompressIndicesTest::compressChar() {
CompressIndices::Result result = MeshTools::compressIndices(
size_t indexCount;
Type indexType;
char* data;
tie(indexCount, indexType, data) = MeshTools::compressIndices(
vector<unsigned int>{1, 2, 3, 0, 4});
QVERIFY(result.indexCount == 5);
QVERIFY(result.indexType == Type::UnsignedByte);
QVERIFY((vector<char>(result.data, result.data+result.indexCount*TypeInfo::sizeOf(result.indexType)) ==
QVERIFY(indexCount == 5);
QVERIFY(indexType == Type::UnsignedByte);
QVERIFY((vector<char>(data, data+indexCount*TypeInfo::sizeOf(indexType)) ==
vector<char>{ 0x01, 0x02, 0x03, 0x00, 0x04 }));
delete[] result.data;
delete[] data;
}
void CompressIndicesTest::compressShort() {
CompressIndices::Result result = MeshTools::compressIndices(
size_t indexCount;
Type indexType;
char* data;
tie(indexCount, indexType, data) = MeshTools::compressIndices(
vector<unsigned int>{1, 256, 0, 5});
QVERIFY(result.indexCount == 4);
QVERIFY(result.indexType == Type::UnsignedShort);
QVERIFY(indexCount == 4);
QVERIFY(indexType == Type::UnsignedShort);
if(!Endianness::isBigEndian()) {
QVERIFY((vector<char>(result.data, result.data+result.indexCount*TypeInfo::sizeOf(result.indexType)) ==
QVERIFY((vector<char>(data, data+indexCount*TypeInfo::sizeOf(indexType)) ==
vector<char>{ 0x01, 0x00,
0x00, 0x01,
0x00, 0x00,
0x05, 0x00 }));
} else {
QVERIFY((vector<char>(result.data, result.data+result.indexCount*TypeInfo::sizeOf(result.indexType)) ==
QVERIFY((vector<char>(data, data+indexCount*TypeInfo::sizeOf(indexType)) ==
vector<char>{ 0x00, 0x01,
0x01, 0x00,
0x00, 0x00,
0x00, 0x05 }));
}
delete[] result.data;
delete[] data;
}
void CompressIndicesTest::compressInt() {
CompressIndices::Result result = MeshTools::compressIndices(
size_t indexCount;
Type indexType;
char* data;
tie(indexCount, indexType, data) = MeshTools::compressIndices(
vector<unsigned int>{65536, 3, 2});
QVERIFY(result.indexCount == 3);
QVERIFY(result.indexType == Type::UnsignedInt);
QVERIFY(indexCount == 3);
QVERIFY(indexType == Type::UnsignedInt);
if(!Endianness::isBigEndian()) {
QVERIFY((vector<char>(result.data, result.data+result.indexCount*TypeInfo::sizeOf(result.indexType)) ==
QVERIFY((vector<char>(data, data+indexCount*TypeInfo::sizeOf(indexType)) ==
vector<char>{ 0x00, 0x00, 0x01, 0x00,
0x03, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00
}));
} else {
QVERIFY((vector<char>(result.data, result.data+result.indexCount*TypeInfo::sizeOf(result.indexType)) ==
QVERIFY((vector<char>(data, data+indexCount*TypeInfo::sizeOf(indexType)) ==
vector<char>{ 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x02
}));
}
delete[] result.data;
delete[] data;
}
}}}

29
src/MeshTools/Test/InterleaveTest.cpp

@ -36,44 +36,47 @@ namespace Magnum { namespace MeshTools { namespace Test {
void InterleaveTest::attributeCount() {
stringstream ss;
Error::setOutput(&ss);
QCOMPARE((Interleave::attributeCount(vector<char>{0, 1, 2},
QCOMPARE((Implementation::Interleave::attributeCount(vector<char>{0, 1, 2},
vector<char>{0, 1, 2, 3, 4, 5})), size_t(0));
QVERIFY(ss.str() == "MeshTools::Interleave: attribute arrays don't have the same length, nothing done.\n");
QVERIFY(ss.str() == "MeshTools::interleave(): attribute arrays don't have the same length, nothing done.\n");
QCOMPARE((Interleave::attributeCount(vector<char>{0, 1, 2},
QCOMPARE((Implementation::Interleave::attributeCount(vector<char>{0, 1, 2},
vector<char>{3, 4, 5})), size_t(3));
}
void InterleaveTest::stride() {
QCOMPARE(Interleave::stride(vector<char>()), size_t(1));
QCOMPARE(Interleave::stride(vector<int>()), size_t(4));
QCOMPARE((Interleave::stride(vector<char>(), vector<int>())), size_t(5));
QCOMPARE(Implementation::Interleave::stride(vector<char>()), size_t(1));
QCOMPARE(Implementation::Interleave::stride(vector<int>()), size_t(4));
QCOMPARE((Implementation::Interleave::stride(vector<char>(), vector<int>())), size_t(5));
}
void InterleaveTest::write() {
Interleave::Result data = MeshTools::interleave(
size_t attributeCount;
size_t stride;
char* data;
tie(attributeCount, stride, data) = MeshTools::interleave(
vector<char>{0, 1, 2},
vector<int>{3, 4, 5},
vector<short>{6, 7, 8});
QCOMPARE(data.attributeCount, size_t(3));
QCOMPARE(data.stride, size_t(7));
size_t size = data.attributeCount*data.stride;
QCOMPARE(attributeCount, size_t(3));
QCOMPARE(stride, size_t(7));
size_t size = attributeCount*stride;
if(!Endianness::isBigEndian()) {
QVERIFY((vector<char>(data.data, data.data+size) == vector<char>{
QVERIFY((vector<char>(data, data+size) == vector<char>{
0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00,
0x01, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00,
0x02, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00
}));
} else {
QVERIFY((vector<char>(data.data, data.data+size) == vector<char>{
QVERIFY((vector<char>(data, data+size) == vector<char>{
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06,
0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x07,
0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08
}));
}
delete[] data.data;
delete[] data;
}
}}}

2
src/MeshTools/Test/TipsifyTest.cpp

@ -67,7 +67,7 @@ TipsifyTest::TipsifyTest(QObject* parent): QObject(parent), indices{
void TipsifyTest::buildAdjacency() {
vector<unsigned int> liveTriangleCount, neighborOffset, neighbors;
Tipsify(indices, vertexCount).buildAdjacency(liveTriangleCount, neighborOffset, neighbors);
Implementation::Tipsify(indices, vertexCount).buildAdjacency(liveTriangleCount, neighborOffset, neighbors);
QVERIFY((liveTriangleCount == vector<unsigned int>{
1, 3, 3, 2,

6
src/MeshTools/Tipsify.cpp

@ -17,7 +17,8 @@
#include <stack>
namespace Magnum { namespace MeshTools {
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Magnum { namespace MeshTools { namespace Implementation {
void Tipsify::operator()(size_t cacheSize) {
/* Neighboring triangles for each vertex, per-vertex live triangle count */
@ -145,4 +146,5 @@ void Tipsify::buildAdjacency(std::vector<unsigned int>& liveTriangleCount, std::
neighbors[neighborOffset[indices[i]+1]++] = i/3;
}
}}
}}}
#endif

33
src/MeshTools/Tipsify.h

@ -16,7 +16,7 @@
*/
/** @file
* @brief Class Magnum::MeshTools::Tipsify, function Magnum::MeshTools::tipsify()
* @brief Function Magnum::MeshTools::tipsify()
*/
#include <cstddef>
@ -26,25 +26,13 @@
namespace Magnum { namespace MeshTools {
/**
@brief %Mesh tipsifier implementation
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
See tipsify() for full documentation.
*/
class MESHTOOLS_EXPORT Tipsify {
public:
/**
* @brief Constructor
*
* See tipsify() for full documentation.
*/
inline Tipsify(std::vector<unsigned int>& indices, unsigned int vertexCount): indices(indices), vertexCount(vertexCount) {}
/**
* @brief Functor
*
* See tipsify() for full documentation.
*/
void operator()(size_t cacheSize);
/**
@ -60,6 +48,9 @@ class MESHTOOLS_EXPORT Tipsify {
const unsigned int vertexCount;
};
}
#endif
/**
@brief %Tipsify the mesh
@param indices Indices array to operate on
@ -71,19 +62,9 @@ array for beter usage of post-transform vertex cache. Algorithm used:
*Pedro V. Sander, Diego Nehab, and Joshua Barczak - Fast Triangle Reordering
for Vertex Locality and Reduced Overdraw, SIGGRAPH 2007,
http://gfx.cs.princeton.edu/pubs/Sander_2007_%3ETR/index.php*.
This is convenience function supplementing direct usage of Tipsify class,
instead of
@code
MeshTools::Tipsify(indices, vertexCount)(cacheSize);
@endcode
you can just write
@code
MeshTools::tipsify(indices, vertexCount, cacheSize);
@endcode
*/
inline void tipsify(std::vector<unsigned int>& indices, unsigned int vertexCount, size_t cacheSize) {
Tipsify(indices, vertexCount)(cacheSize);
Implementation::Tipsify(indices, vertexCount)(cacheSize);
}
}}

Loading…
Cancel
Save