diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 971e64c5e..67ecd37bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -std=c++0x") include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CORRADE_INCLUDE_DIR}) add_subdirectory(Math) +add_subdirectory(MeshTools) add_subdirectory(Primitives) set(Magnum_SRCS diff --git a/src/MeshBuilder.h b/src/MeshBuilder.h index a8cd91a3c..0e8d07a6a 100644 --- a/src/MeshBuilder.h +++ b/src/MeshBuilder.h @@ -30,18 +30,25 @@ namespace Magnum { +namespace MeshTools { + template class AbstractTool; +} + /** @brief Mesh builder @tparam Vertex Vertex data Class for building meshes with triangle primitive from scratch or from -prefabricated data and modifying them (adding/removing faces, cleaning duplicate -vertices etc.). +prefabricated data and modifying them using MeshBuilder alone or tools from +MeshTools namespace. @todo Make it more generic for meshes with texture coordinates etc. */ template class MeshBuilder { + friend class MeshTools::AbstractTool; + public: + /** * @brief Destructor * @@ -112,121 +119,6 @@ template class MeshBuilder { _indices.push_back(third); } - /** - * @brief Subdivide mesh - * @param interpolator Functor or function pointer which interpolates - * two adjacent vertices: Vertex interpolator(Vertex a, Vertex - * b) - * - * Goes through all triangle faces and subdivides them in four new. - * Cleaning the mesh is up to user. - */ - template void subdivide(Interpolator interpolator) { - size_t indexCount = _indices.size(); - _indices.reserve(_indices.size()*4); - - /* Subdivide each face to four new */ - for(size_t i = 0; i != indexCount; i += 3) { - /* Interpolate each side */ - unsigned int newVertices[3]; - for(int j = 0; j != 3; ++j) - newVertices[j] = addVertex(interpolator(_vertices[_indices[i+j]], _vertices[_indices[i+(j+1)%3]])); - - /* - * Add three new faces (0, 1, 3) and update original (2) - * - * orig 0 - * / \ - * / 0 \ - * / \ - * new 0 ----- new 2 - * / \ / \ - * / 1 \ 2 / 3 \ - * / \ / \ - * orig 1 ----- new 1 ---- orig 2 - */ - addFace(_indices[i], newVertices[0], newVertices[2]); - addFace(newVertices[0], _indices[i+1], newVertices[1]); - addFace(newVertices[2], newVertices[1], _indices[i+2]); - for(size_t j = 0; j != 3; ++j) - _indices[i+j] = newVertices[j]; - } - } - - /** - * @brief Clean the mesh - * @param epsilon Epsilon value, vertices nearer than this - * distance will be melt together. - * - * Removes duplicate vertices from the mesh. With template parameter - * @c vertexSize you can specify how many initial vertex fields are - * important (for example, when dealing with perspective in 3D space, - * only first three fields of otherwise 4D vertex are important). - */ - template void cleanMesh(typename Vertex::Type epsilon = EPSILON) { - if(_indices.empty()) return; - - /* Get mesh bounds */ - Vertex min, max; - for(size_t i = 0; i != Vertex::Size; ++i) { - min[i] = std::numeric_limits::max(); - max[i] = std::numeric_limits::min(); - } - for(auto it = _vertices.cbegin(); it != _vertices.cend(); ++it) - for(size_t i = 0; i != vertexSize; ++i) - if((*it)[i] < min[i]) - min[i] = (*it)[i]; - else if((*it)[i] > max[i]) - max[i] = (*it)[i]; - - /* Make epsilon so large that size_t can index all vertices inside - mesh bounds. */ - Vertex size = max-min; - for(size_t i = 0; i != Vertex::Size; ++i) - if(static_cast(size[i]/std::numeric_limits::max()) > epsilon) - epsilon = static_cast(size[i]/std::numeric_limits::max()); - - /* First go with original vertex coordinates, then move them by - epsilon/2 in each direction. */ - Vertex moved; - for(size_t moving = 0; moving <= vertexSize; ++moving) { - - /* Under each index is pointer to face which contains given vertex - and index of vertex in the face. */ - std::unordered_map, HashedVertex, IndexHash> table; - - /* Reserve space for all vertices */ - table.reserve(_vertices.size()); - - /* Go through all faces' vertices */ - for(auto it = _indices.begin(); it != _indices.end(); ++it) { - /* Index of a vertex in vertexSize-dimensional table */ - size_t index[vertexSize]; - for(size_t ii = 0; ii != vertexSize; ++ii) - index[ii] = (_vertices[*it][ii]+moved[ii]-min[ii])/epsilon; - - /* Try inserting the vertex into table, if it already - exists, change vertex pointer of the face to already - existing vertex */ - HashedVertex v(*it, table.size()); - auto result = table.insert(std::pair, HashedVertex>(index, v)); - *it = result.first->second.newIndex; - } - - /* Shrink vertices array */ - std::vector vertices(table.size()); - for(auto it = table.cbegin(); it != table.cend(); ++it) - vertices[it->second.newIndex] = _vertices[it->second.oldIndex]; - std::swap(vertices, _vertices); - - /* Move vertex coordinates by epsilon/2 in next direction */ - if(moving != Vertex::Size) { - moved = Vertex(); - moved[moving] = epsilon/2; - } - } - } - /** * @brief Build indexed mesh and fill existing buffers with it * @param mesh Mesh. The mesh primitive is set to @@ -267,22 +159,6 @@ template class MeshBuilder { std::vector _indices; std::vector _vertices; - template class IndexHash { - public: - inline size_t operator()(const Math::Vector& data) const { - size_t a = 0; - for(size_t i = 0; i != vertexSize; ++i) - a ^= data[i]; - return a; - } - }; - - struct HashedVertex { - unsigned int oldIndex, newIndex; - - HashedVertex(unsigned int oldIndex, unsigned int newIndex): oldIndex(oldIndex), newIndex(newIndex) {} - }; - struct IndexBuilder { template static void run(IndexedMesh* mesh, const std::vector& _indices, Buffer::Usage indexBufferUsage) { /* Compress face array to index array. Using diff --git a/src/MeshTools/Clean.h b/src/MeshTools/Clean.h new file mode 100644 index 000000000..f8fbb98e4 --- /dev/null +++ b/src/MeshTools/Clean.h @@ -0,0 +1,157 @@ +#ifndef Magnum_MeshTools_Clean_h +#define Magnum_MeshTools_Clean_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::MeshTools::Clean + */ + +#include "AbstractTool.h" + +namespace Magnum { namespace MeshTools { + +/** +@brief %Mesh cleaner implementation + +See clean() for full documentation. +*/ +template class Clean: public AbstractTool { + public: + /** @copydoc AbstractTool::AbstractTool() */ + inline Clean(MeshBuilder& builder): AbstractTool(builder) {} + + /** + * @brief Functor + * + * See clean() for full documentation. + */ + void run(typename Vertex::Type epsilon = EPSILON) { + if(this->indices.empty()) return; + + /* Get mesh bounds */ + Vertex min, max; + for(size_t i = 0; i != Vertex::Size; ++i) { + min[i] = std::numeric_limits::max(); + max[i] = std::numeric_limits::min(); + } + for(auto it = this->vertices.cbegin(); it != this->vertices.cend(); ++it) + for(size_t i = 0; i != vertexSize; ++i) + if((*it)[i] < min[i]) + min[i] = (*it)[i]; + else if((*it)[i] > max[i]) + max[i] = (*it)[i]; + + /* Make epsilon so large that size_t can index all vertices inside + mesh bounds. */ + Vertex size = max-min; + for(size_t i = 0; i != Vertex::Size; ++i) + if(static_cast(size[i]/std::numeric_limits::max()) > epsilon) + epsilon = static_cast(size[i]/std::numeric_limits::max()); + + /* First go with original vertex coordinates, then move them by + epsilon/2 in each direction. */ + Vertex moved; + for(size_t moving = 0; moving <= vertexSize; ++moving) { + + /* Under each index is pointer to face which contains given vertex + and index of vertex in the face. */ + std::unordered_map, HashedVertex, IndexHash> table; + + /* Reserve space for all vertices */ + table.reserve(this->vertices.size()); + + /* Go through all faces' vertices */ + for(auto it = this->indices.begin(); it != this->indices.end(); ++it) { + /* Index of a vertex in vertexSize-dimensional table */ + size_t index[vertexSize]; + for(size_t ii = 0; ii != vertexSize; ++ii) + index[ii] = (this->vertices[*it][ii]+moved[ii]-min[ii])/epsilon; + + /* Try inserting the vertex into table, if it already + exists, change vertex pointer of the face to already + existing vertex */ + HashedVertex v(*it, table.size()); + auto result = table.insert(std::pair, HashedVertex>(index, v)); + *it = result.first->second.newIndex; + } + + /* Shrink vertices array */ + std::vector newVertices(table.size()); + for(auto it = table.cbegin(); it != table.cend(); ++it) + newVertices[it->second.newIndex] = this->vertices[it->second.oldIndex]; + std::swap(newVertices, this->vertices); + + /* Move vertex coordinates by epsilon/2 in next direction */ + if(moving != Vertex::Size) { + moved = Vertex(); + moved[moving] = epsilon/2; + } + } + } + + private: + class IndexHash { + public: + inline size_t operator()(const Math::Vector& data) const { + size_t a = 0; + for(size_t i = 0; i != vertexSize; ++i) + a ^= data[i]; + return a; + } + }; + + struct HashedVertex { + unsigned int oldIndex, newIndex; + + HashedVertex(unsigned int oldIndex, unsigned int newIndex): oldIndex(oldIndex), newIndex(newIndex) {} + }; +}; + +/** +@brief %Clean the mesh +@tparam Vertex Vertex data type (the same as in MeshBuilder) +@tparam vertexSize How many initial vertex fields are important (for example, + when dealing with perspective in 3D space, only first three fields of + otherwise 4D vertex are important) +@param builder %Mesh builder to operate on +@param epsilon Epsilon value, vertices nearer than this + distance will be melt together. + +Removes duplicate vertices from the mesh. + +This is convenience function supplementing direct usage of Clean class, +instead of +@code +MeshBuilder builder; +MeshTools::Clean(builder).run(epsilon); +@endcode +you can just write +@code +MeshTools::clean(builder, epsilon); +@endcode +However, when you want to specify @c vertexSize template parameter, you have +to explicitly specify both of them: +@code +MeshTools::clean(builder, epsilon); +@endcode +*/ +template inline void clean(MeshBuilder& builder, typename Vertex::Type epsilon = EPSILON) { + Clean(builder).run(epsilon); +} + +}} + +#endif diff --git a/src/MeshTools/Subdivide.h b/src/MeshTools/Subdivide.h new file mode 100644 index 000000000..3d757f7cb --- /dev/null +++ b/src/MeshTools/Subdivide.h @@ -0,0 +1,102 @@ +#ifndef Magnum_MeshTools_Subdivide_h +#define Magnum_MeshTools_Subdivide_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::MeshTools::Subdivide + */ + +#include "AbstractTool.h" + +namespace Magnum { namespace MeshTools { + +/** +@brief %Mesh subdivisor implementation + +See subdivide() for full documentation. +*/ +template class Subdivide: public AbstractTool { + public: + /** @copydoc AbstractTool::AbstractTool() */ + inline Subdivide(MeshBuilder& builder): AbstractTool(builder) {} + + /** + * @brief Functor + * + * See subdivide() for full documentation. + */ + void run(Interpolator interpolator) { + size_t indexCount = this->indices.size(); + this->indices.reserve(this->indices.size()*4); + + /* Subdivide each face to four new */ + for(size_t i = 0; i != indexCount; i += 3) { + /* Interpolate each side */ + unsigned int newVertices[3]; + for(int j = 0; j != 3; ++j) + newVertices[j] = this->builder.addVertex(interpolator(this->vertices[this->indices[i+j]], this->vertices[this->indices[i+(j+1)%3]])); + + /* + * Add three new faces (0, 1, 3) and update original (2) + * + * orig 0 + * / \ + * / 0 \ + * / \ + * new 0 ----- new 2 + * / \ / \ + * / 1 \ 2 / 3 \ + * / \ / \ + * orig 1 ----- new 1 ---- orig 2 + */ + this->builder.addFace(this->indices[i], newVertices[0], newVertices[2]); + this->builder.addFace(newVertices[0], this->indices[i+1], newVertices[1]); + this->builder.addFace(newVertices[2], newVertices[1], this->indices[i+2]); + for(size_t j = 0; j != 3; ++j) + this->indices[i+j] = newVertices[j]; + } + } +}; + +/** +@brief %Subdivide the mesh +@tparam Vertex Vertex data type (the same as in MeshBuilder) +@tparam Interpolator See @c interpolator function parameter +@param builder %Mesh builder to operate on +@param interpolator Functor or function pointer which interpolates + two adjacent vertices: Vertex interpolator(Vertex a, Vertex b) + +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 +MeshBuilder builder; +MeshTools::Subdivide(builder).run(interpolator); +@endcode +you can just write +@code +MeshTools::subdivide(builder, interpolator); +@endcode +*/ +template inline void subdivide(MeshBuilder& builder, Interpolator interpolator) { + Subdivide(builder).run(interpolator); +} + +}} + +#endif diff --git a/src/MeshTools/Test/CMakeLists.txt b/src/MeshTools/Test/CMakeLists.txt new file mode 100644 index 000000000..f12c60f3e --- /dev/null +++ b/src/MeshTools/Test/CMakeLists.txt @@ -0,0 +1,4 @@ +corrade_add_test(CleanTest CleanTest.h CleanTest.cpp) +corrade_add_test(SubdivideTest SubdivideTest.h SubdivideTest.cpp) +corrade_add_test(SubdivideCleanBenchmark SubdivideCleanBenchmark.h SubdivideCleanBenchmark.cpp) +target_link_libraries(SubdivideCleanBenchmark ${MAGNUM_PRIMITIVES_LIBRARY}) diff --git a/src/MeshTools/Test/CleanTest.cpp b/src/MeshTools/Test/CleanTest.cpp new file mode 100644 index 000000000..bebdeedc2 --- /dev/null +++ b/src/MeshTools/Test/CleanTest.cpp @@ -0,0 +1,44 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "CleanTest.h" + +#include + +#include "MeshTools/Clean.h" + +QTEST_APPLESS_MAIN(Magnum::MeshTools::Test::CleanTest) + +using namespace std; + +namespace Magnum { namespace MeshTools { namespace Test { + +void CleanTest::cleanMesh() { + MeshBuilder builder; + builder.addVertex(1); + builder.addVertex(2); + builder.addVertex(1); + builder.addVertex(4); + builder.addFace(0, 1, 2); + builder.addFace(1, 2, 3); + + MeshTools::clean(builder, 1); + + /* Verify cleanup */ + QVERIFY((builder.vertices() == vector{1, 2, 4})); + QVERIFY((builder.indices() == vector{0, 1, 0, 1, 0, 2})); +} + +}}} diff --git a/src/MeshTools/Test/CleanTest.h b/src/MeshTools/Test/CleanTest.h new file mode 100644 index 000000000..fa28c6a11 --- /dev/null +++ b/src/MeshTools/Test/CleanTest.h @@ -0,0 +1,48 @@ +#ifndef Magnum_MeshTools_Test_CleanTest_h +#define Magnum_MeshTools_Test_CleanTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace MeshTools { namespace Test { + +class CleanTest: public QObject { + Q_OBJECT + + private slots: + void cleanMesh(); + + private: + class Vector1 { + public: + static const size_t Size = 1; + typedef int Type; + + Vector1(): data(0) {} + Vector1(int i): data(i) {} + int operator[](size_t i) const { return data; } + int& operator[](size_t i) { return data; } + bool operator==(Vector1 i) const { return i.data == data; } + Vector1 operator-(Vector1 i) const { return data-i.data; } + + private: + int data; + }; +}; + +}}} + +#endif diff --git a/src/MeshTools/Test/SubdivideCleanBenchmark.cpp b/src/MeshTools/Test/SubdivideCleanBenchmark.cpp new file mode 100644 index 000000000..2c52ae417 --- /dev/null +++ b/src/MeshTools/Test/SubdivideCleanBenchmark.cpp @@ -0,0 +1,78 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "SubdivideCleanBenchmark.h" + +#include + +#include "MeshBuilder.h" +#include "Primitives/Icosphere.h" +#include "MeshTools/Clean.h" +#include "MeshTools/Subdivide.h" + +QTEST_APPLESS_MAIN(Magnum::MeshTools::Test::SubdivideCleanBenchmark) + +namespace Magnum { namespace MeshTools { namespace Test { + +void SubdivideCleanBenchmark::subdivide() { + QBENCHMARK { + MeshBuilder builder; + builder.setData(Primitives::Icosahedron::vertices, Primitives::Icosahedron::indices, 12, 60); + + /* Subdivide 5 times */ + MeshTools::subdivide(builder, interpolator); + MeshTools::subdivide(builder, interpolator); + MeshTools::subdivide(builder, interpolator); + MeshTools::subdivide(builder, interpolator); + MeshTools::subdivide(builder, interpolator); + } +} + +void SubdivideCleanBenchmark::subdivideAndCleanMeshAfter() { + QBENCHMARK { + MeshBuilder builder; + builder.setData(Primitives::Icosahedron::vertices, Primitives::Icosahedron::indices, 12, 60); + + /* Subdivide 5 times */ + MeshTools::subdivide(builder, interpolator); + MeshTools::subdivide(builder, interpolator); + MeshTools::subdivide(builder, interpolator); + MeshTools::subdivide(builder, interpolator); + MeshTools::subdivide(builder, interpolator); + + MeshTools::clean(builder); + } +} + +void SubdivideCleanBenchmark::subdivideAndCleanMeshBetween() { + QBENCHMARK { + MeshBuilder builder; + builder.setData(Primitives::Icosahedron::vertices, Primitives::Icosahedron::indices, 12, 60); + + /* Subdivide 5 times */ + MeshTools::subdivide(builder, interpolator); + MeshTools::clean(builder); + MeshTools::subdivide(builder, interpolator); + MeshTools::clean(builder); + MeshTools::subdivide(builder, interpolator); + MeshTools::clean(builder); + MeshTools::subdivide(builder, interpolator); + MeshTools::clean(builder); + MeshTools::subdivide(builder, interpolator); + MeshTools::clean(builder); + } +} + +}}} diff --git a/src/Test/MeshBuilderBenchmark.h b/src/MeshTools/Test/SubdivideCleanBenchmark.h similarity index 81% rename from src/Test/MeshBuilderBenchmark.h rename to src/MeshTools/Test/SubdivideCleanBenchmark.h index eec3d0dd1..390cb54e2 100644 --- a/src/Test/MeshBuilderBenchmark.h +++ b/src/MeshTools/Test/SubdivideCleanBenchmark.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Test_MeshBuilderBenchmark_h -#define Magnum_Test_MeshBuilderBenchmark_h +#ifndef Magnum_MeshTools_Test_SubdivideCleanBenchmark_h +#define Magnum_MeshTools_Test_SubdivideCleanBenchmark_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -19,9 +19,9 @@ #include "Magnum.h" -namespace Magnum { namespace Test { +namespace Magnum { namespace MeshTools { namespace Test { -class MeshBuilderBenchmark: public QObject { +class SubdivideCleanBenchmark: public QObject { Q_OBJECT private slots: @@ -35,5 +35,6 @@ class MeshBuilderBenchmark: public QObject { } }; -}} +}}} + #endif diff --git a/src/MeshTools/Test/SubdivideTest.cpp b/src/MeshTools/Test/SubdivideTest.cpp new file mode 100644 index 000000000..d94ec11a0 --- /dev/null +++ b/src/MeshTools/Test/SubdivideTest.cpp @@ -0,0 +1,51 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "SubdivideTest.h" + +#include + +#include "MeshBuilder.h" +#include "MeshTools/Clean.h" +#include "MeshTools/Subdivide.h" + +QTEST_APPLESS_MAIN(Magnum::MeshTools::Test::SubdivideTest) + +using namespace std; + +namespace Magnum { namespace MeshTools { namespace Test { + +void SubdivideTest::subdivide() { + MeshBuilder builder; + builder.addVertex(0); + builder.addVertex(2); + builder.addVertex(6); + builder.addVertex(8); + builder.addFace(0, 1, 2); + builder.addFace(1, 2, 3); + + MeshTools::subdivide(builder, interpolator); + QVERIFY(builder.indices().size() == 24); + + QVERIFY((builder.vertices() == vector{0, 2, 6, 8, 1, 4, 3, 4, 7, 5})); + QVERIFY((builder.indices() == vector{4, 5, 6, 7, 8, 9, 0, 4, 6, 4, 1, 5, 6, 5, 2, 1, 7, 9, 7, 2, 8, 9, 8, 3})); + + MeshTools::clean(builder, 1); + + /* Vertices 0, 1, 2, 3, 4, 5, 6, 7, 8 */ + QVERIFY(builder.vertices().size() == 9); +} + +}}} diff --git a/src/MeshTools/Test/SubdivideTest.h b/src/MeshTools/Test/SubdivideTest.h new file mode 100644 index 000000000..d53006127 --- /dev/null +++ b/src/MeshTools/Test/SubdivideTest.h @@ -0,0 +1,50 @@ +#ifndef Magnum_MeshTools_Test_SubdivideTest_h +#define Magnum_MeshTools_Test_SubdivideTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace MeshTools { namespace Test { + +class SubdivideTest: public QObject { + Q_OBJECT + + private slots: + void subdivide(); + + private: + class Vector1 { + public: + static const size_t Size = 1; + typedef int Type; + + Vector1(): data(0) {} + Vector1(int i): data(i) {} + int operator[](size_t i) const { return data; } + int& operator[](size_t i) { return data; } + bool operator==(Vector1 i) const { return i.data == data; } + Vector1 operator-(Vector1 i) const { return data-i.data; } + + private: + int data; + }; + + inline static Vector1 interpolator(Vector1 a, Vector1 b) { return (a[0]+b[0])/2; } +}; + +}}} + +#endif diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index be254de33..6f315ba01 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -2,5 +2,3 @@ corrade_add_test(ObjectTest ObjectTest.h ObjectTest.cpp Magnum) corrade_add_test(CameraTest CameraTest.h CameraTest.cpp Magnum) corrade_add_test(SceneTest SceneTest.h SceneTest.cpp Magnum) corrade_add_test(MeshBuilderTest MeshBuilderTest.h MeshBuilderTest.cpp Magnum) -corrade_add_test(MeshBuilderBenchmark MeshBuilderBenchmark.h MeshBuilderBenchmark.cpp Magnum) -target_link_libraries(MeshBuilderBenchmark ${MAGNUM_PRIMITIVES_LIBRARY}) diff --git a/src/Test/MeshBuilderBenchmark.cpp b/src/Test/MeshBuilderBenchmark.cpp deleted file mode 100644 index bdf6754e8..000000000 --- a/src/Test/MeshBuilderBenchmark.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright © 2010, 2011, 2012 Vladimír Vondruš - - This file is part of Magnum. - - Magnum is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License version 3 - only, as published by the Free Software Foundation. - - Magnum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License version 3 for more details. -*/ - -#include "MeshBuilderBenchmark.h" - -#include - -#include "MeshBuilder.h" -#include "Magnum.h" -#include "Primitives/Icosphere.h" - -QTEST_APPLESS_MAIN(Magnum::Test::MeshBuilderBenchmark) - -namespace Magnum { namespace Test { - -void MeshBuilderBenchmark::subdivide() { - QBENCHMARK { - MeshBuilder builder; - builder.setData(Primitives::Icosahedron::vertices, Primitives::Icosahedron::indices, 12, 60); - - /* Subdivide 5 times */ - builder.subdivide(interpolator); - builder.subdivide(interpolator); - builder.subdivide(interpolator); - builder.subdivide(interpolator); - builder.subdivide(interpolator); - } -} - -void MeshBuilderBenchmark::subdivideAndCleanMeshAfter() { - QBENCHMARK { - MeshBuilder builder; - builder.setData(Primitives::Icosahedron::vertices, Primitives::Icosahedron::indices, 12, 60); - - /* Subdivide 5 times */ - builder.subdivide(interpolator); - builder.subdivide(interpolator); - builder.subdivide(interpolator); - builder.subdivide(interpolator); - builder.subdivide(interpolator); - - builder.cleanMesh(); - } -} - -void MeshBuilderBenchmark::subdivideAndCleanMeshBetween() { - QBENCHMARK { - MeshBuilder builder; - builder.setData(Primitives::Icosahedron::vertices, Primitives::Icosahedron::indices, 12, 60); - - /* Subdivide 5 times */ - builder.subdivide(interpolator); - builder.cleanMesh(); - builder.subdivide(interpolator); - builder.cleanMesh(); - builder.subdivide(interpolator); - builder.cleanMesh(); - builder.subdivide(interpolator); - builder.cleanMesh(); - builder.subdivide(interpolator); - builder.cleanMesh(); - } -} - -}} diff --git a/src/Test/MeshBuilderTest.cpp b/src/Test/MeshBuilderTest.cpp index a42400d69..a46a6969e 100644 --- a/src/Test/MeshBuilderTest.cpp +++ b/src/Test/MeshBuilderTest.cpp @@ -26,18 +26,18 @@ using namespace std; namespace Magnum { namespace Test { void MeshBuilderTest::setData() { - MeshBuilder builder; + MeshBuilder builder; - Vector1 vertexData[] = { 1, 2, 3, 4 }; + unsigned int vertexData[] = { 1, 2, 3, 4 }; GLubyte indexData[] = { 0, 1, 2, 1, 2, 3 }; builder.setData(vertexData, indexData, 4, 6); - QVERIFY((builder.vertices() == vector{1, 2, 3, 4})); + QVERIFY((builder.vertices() == vector{1, 2, 3, 4})); QVERIFY((builder.indices() == vector{0, 1, 2, 1, 2, 3})); } void MeshBuilderTest::addFace() { - MeshBuilder builder; + MeshBuilder builder; builder.addVertex(1); builder.addVertex(2); builder.addVertex(3); @@ -45,45 +45,8 @@ void MeshBuilderTest::addFace() { builder.addFace(0, 1, 2); builder.addFace(1, 2, 3); - QVERIFY((builder.vertices() == vector{1, 2, 3, 4})); + QVERIFY((builder.vertices() == vector{1, 2, 3, 4})); QVERIFY((builder.indices() == vector{0, 1, 2, 1, 2, 3})); } -void MeshBuilderTest::cleanMesh() { - MeshBuilder builder; - builder.addVertex(1); - builder.addVertex(2); - builder.addVertex(1); - builder.addVertex(4); - builder.addFace(0, 1, 2); - builder.addFace(1, 2, 3); - - builder.cleanMesh(1); - - /* Verify cleanup */ - QVERIFY((builder.vertices() == vector{1, 2, 4})); - QVERIFY((builder.indices() == vector{0, 1, 0, 1, 0, 2})); -} - -void MeshBuilderTest::subdivide() { - MeshBuilder builder; - builder.addVertex(0); - builder.addVertex(2); - builder.addVertex(6); - builder.addVertex(8); - builder.addFace(0, 1, 2); - builder.addFace(1, 2, 3); - - builder.subdivide(interpolator); - QVERIFY(builder.indices().size() == 24); - - QVERIFY((builder.vertices() == vector{0, 2, 6, 8, 1, 4, 3, 4, 7, 5})); - QVERIFY((builder.indices() == vector{4, 5, 6, 7, 8, 9, 0, 4, 6, 4, 1, 5, 6, 5, 2, 1, 7, 9, 7, 2, 8, 9, 8, 3})); - - builder.cleanMesh(1); - - /* Vertices 0, 1, 2, 3, 4, 5, 6, 7, 8 */ - QVERIFY(builder.vertices().size() == 9); -} - }} diff --git a/src/Test/MeshBuilderTest.h b/src/Test/MeshBuilderTest.h index ff8a462cf..0dbbead99 100644 --- a/src/Test/MeshBuilderTest.h +++ b/src/Test/MeshBuilderTest.h @@ -25,28 +25,6 @@ class MeshBuilderTest: public QObject { private slots: void setData(); void addFace(); - void cleanMesh(); - void subdivide(); - - private: - class Vector1 { - public: - static const size_t Size = 1; - typedef int Type; - - Vector1(): data(0) {} - Vector1(int i): data(i) {} - int operator[](size_t i) const { return data; } - int& operator[](size_t i) { return data; } - bool operator==(int i) const { return i == data; } - bool operator==(Vector1 i) const { return i.data == data; } - Vector1 operator-(Vector1 i) const { return data-i.data; } - - private: - int data; - }; - - inline static Vector1 interpolator(Vector1 a, Vector1 b) { return (a[0]+b[0])/2; } }; }}