From b57a9f10279a45415ba0f3b43c56234de7aeffe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 17 Mar 2020 20:31:35 +0100 Subject: [PATCH] MeshTools: tools for generating index buffers out of various primitives. --- doc/changelog.dox | 6 + src/Magnum/Mesh.h | 4 + src/Magnum/MeshTools/CMakeLists.txt | 2 + src/Magnum/MeshTools/GenerateIndices.cpp | 146 ++++++++++ src/Magnum/MeshTools/GenerateIndices.h | 132 +++++++++ src/Magnum/MeshTools/Test/CMakeLists.txt | 2 + .../MeshTools/Test/GenerateIndicesTest.cpp | 264 ++++++++++++++++++ 7 files changed, 556 insertions(+) create mode 100644 src/Magnum/MeshTools/GenerateIndices.cpp create mode 100644 src/Magnum/MeshTools/GenerateIndices.h create mode 100644 src/Magnum/MeshTools/Test/GenerateIndicesTest.cpp diff --git a/doc/changelog.dox b/doc/changelog.dox index 384727118..8137075f4 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -150,6 +150,12 @@ See also: into per-vertex - New @ref MeshTools::concatenate() and @ref MeshTools::concatenateInto() tool for batching multiple generic meshes together +- New family of @ref MeshTools::generateLineStripIndices(), + @ref MeshTools::generateLineLoopIndices(), + @ref MeshTools::generateTriangleStripIndices() and + @ref MeshTools::generateTriangleFanIndices() utilities for converting + various mesh types to plain indexed @ref MeshPrimitive::Lines and + @ref MeshPrimitive::Triangles @subsubsection changelog-latest-new-platform Platform libraries diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index ec50012c7..62d1def44 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -89,6 +89,7 @@ enum class MeshPrimitive: UnsignedInt { * * Corresponds to @ref GL::MeshPrimitive::LineLoop. Not supported on * Vulkan, D3D or Metal. + * @see @ref MeshTools::generateLineLoopIndices() */ LineLoop, @@ -101,6 +102,7 @@ enum class MeshPrimitive: UnsignedInt { * @m_class{m-doc-external} [D3D_PRIMITIVE_TOPOLOGY_LINESTRIP](https://docs.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_primitive_topology) * or @m_class{m-doc-external} [MTLPrimitiveTypeLineStrip](https://developer.apple.com/documentation/metal/mtlprimitivetype/mtlprimitivetypelinestrip?language=objc). * @m_keywords{D3D_PRIMITIVE_TOPOLOGY_LINESTRIP MTLPrimitiveTypeLineStrip} + * @see @ref MeshTools::generateLineStripIndices() */ LineStrip, @@ -124,6 +126,7 @@ enum class MeshPrimitive: UnsignedInt { * @m_class{m-doc-external} [D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP](https://docs.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_primitive_topology) * or @m_class{m-doc-external} [MTLPrimitiveTypeTriangleStrip](https://developer.apple.com/documentation/metal/mtlprimitivetype/mtlprimitivetypetrianglestrip?language=objc). * @m_keywords{D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP MTLPrimitiveTypeTriangleStrip} + * @see @ref MeshTools::generateTriangleStripIndices() */ TriangleStrip, @@ -134,6 +137,7 @@ enum class MeshPrimitive: UnsignedInt { * Corresponds to @ref GL::MeshPrimitive::TriangleFan / * @def_vk_keyword{PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,PrimitiveTopology}. Not * supported on D3D or Metal. + * @see @ref MeshTools::generateTriangleFanIndices() */ TriangleFan, diff --git a/src/Magnum/MeshTools/CMakeLists.txt b/src/Magnum/MeshTools/CMakeLists.txt index 67cc0d2ae..8efc3394b 100644 --- a/src/Magnum/MeshTools/CMakeLists.txt +++ b/src/Magnum/MeshTools/CMakeLists.txt @@ -34,6 +34,7 @@ set(MagnumMeshTools_GracefulAssert_SRCS Concatenate.cpp Duplicate.cpp FlipNormals.cpp + GenerateIndices.cpp GenerateNormals.cpp Interleave.cpp RemoveDuplicates.cpp) @@ -44,6 +45,7 @@ set(MagnumMeshTools_HEADERS Concatenate.h Duplicate.h FlipNormals.h + GenerateIndices.h GenerateNormals.h Interleave.h RemoveDuplicates.h diff --git a/src/Magnum/MeshTools/GenerateIndices.cpp b/src/Magnum/MeshTools/GenerateIndices.cpp new file mode 100644 index 000000000..1b01c5342 --- /dev/null +++ b/src/Magnum/MeshTools/GenerateIndices.cpp @@ -0,0 +1,146 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "GenerateIndices.h" + +#include +#include + +namespace Magnum { namespace MeshTools { + +void generateLineStripIndicesInto(const UnsignedInt vertexCount, const Containers::StridedArrayView1D& indices) { + CORRADE_ASSERT(vertexCount >= 2, + "MeshTools::generateLineStripIndicesInto(): expected at least two vertices, got" << vertexCount, ); + CORRADE_ASSERT(indices.size() == 2*(vertexCount - 1), + "MeshTools::generateLineStripIndicesInto(): bad output size, expected" << 2*(vertexCount - 1) << "but got" << indices.size(), ); + + /* + 1 --- 2 1 2 --- 3 4 + / \ / \ + / \ => / \ + / \ / \ + 0 3 0 5 + */ + for(std::size_t i = 0; i != vertexCount - 1; ++i) { + indices[i*2 + 0] = i; + indices[i*2 + 1] = i + 1; + } +} + +Containers::Array generateLineStripIndices(const UnsignedInt vertexCount) { + Containers::Array indices{Containers::NoInit, 2*(vertexCount - 1)}; + generateLineStripIndicesInto(vertexCount, indices); + return indices; +} + +void generateLineLoopIndicesInto(const UnsignedInt vertexCount, const Containers::StridedArrayView1D& indices) { + CORRADE_ASSERT(vertexCount >= 2, + "MeshTools::generateLineLoopIndicesInto(): expected at least two vertices, got" << vertexCount, ); + CORRADE_ASSERT(indices.size() == 2*vertexCount, + "MeshTools::generateLineLoopIndicesInto(): bad output size, expected" << 2*vertexCount << "but got" << indices.size(), ); + + /* + Same as with line strip, with one additional line segment at the end. + + 1 --- 2 1 2 --- 3 4 + / \ / \ + / \ => / \ + / \ / \ + 0 ----------- 3 0 7 ----------- 6 5 + */ + for(std::size_t i = 0; i != vertexCount - 1; ++i) { + indices[i*2 + 0] = i; + indices[i*2 + 1] = i + 1; + } + indices[2*vertexCount - 2] = vertexCount - 1; + indices[2*vertexCount - 1] = 0; +} + +Containers::Array generateLineLoopIndices(const UnsignedInt vertexCount) { + Containers::Array indices{Containers::NoInit, 2*vertexCount}; + generateLineLoopIndicesInto(vertexCount, indices); + return indices; +} + +void generateTriangleStripIndicesInto(const UnsignedInt vertexCount, const Containers::StridedArrayView1D& indices) { + CORRADE_ASSERT(vertexCount >= 3, + "MeshTools::generateTriangleStripIndicesInto(): expected at least three vertices, got" << vertexCount, ); + CORRADE_ASSERT(indices.size() == 3*(vertexCount - 2), + "MeshTools::generateTriangleStripIndicesInto(): bad output size, expected" << 3*(vertexCount - 2) << "but got" << indices.size(), ); + + /* + Triangles starting with odd vertices (marked with !) have the first two + indices swapped to preserve winding. + + 0 ----- 2 ----- 4 0 ----- 2 3 6 ----- 8 9 + \ / \ / \ \ / / \ \ / / \ + \ / \ / \ => \ / / \ \ / / \ + \ / \ / \ \ / / ! \ \ / / ! \ + 1 ----- 3 ----- 5 1 4 ----- 5 7 10 ---- 11 + */ + for(std::size_t i = 0; i != vertexCount - 2; ++i) { + indices[i*3 + 0] = i % 2 ? i + 1 : i; + indices[i*3 + 1] = i % 2 ? i : i + 1; + indices[i*3 + 2] = i + 2; + } +} + +Containers::Array generateTriangleStripIndices(const UnsignedInt vertexCount) { + Containers::Array indices{Containers::NoInit, 3*(vertexCount - 2)}; + generateTriangleStripIndicesInto(vertexCount, indices); + return indices; +} + +void generateTriangleFanIndicesInto(const UnsignedInt vertexCount, const Containers::StridedArrayView1D& indices) { + CORRADE_ASSERT(vertexCount >= 3, + "MeshTools::generateTriangleFanIndicesInto(): expected at least three vertices, got" << vertexCount, ); + CORRADE_ASSERT(indices.size() == 3*(vertexCount - 2), + "MeshTools::generateTriangleFanIndicesInto(): bad output size, expected" << 3*(vertexCount - 2) << "but got" << indices.size(), ); + + /* 10 8 ----- 7 5 + 4 ----- 3 / \ \ / / \ + / \ / \ / \ \ / / \ + / \ / \ / \ \ / / \ + / \ / \ 11 ----- 9 6 3 ----- 4 + 5 ----- 0 ----- 2 => 0 ----- 2 + \ / \ / + \ / \ / + \ / \ / + 1 1 + */ + for(std::size_t i = 0; i != vertexCount - 2; ++i) { + indices[i*3 + 0] = 0; + indices[i*3 + 1] = i + 1; + indices[i*3 + 2] = i + 2; + } +} + +Containers::Array generateTriangleFanIndices(const UnsignedInt vertexCount) { + Containers::Array indices{Containers::NoInit, 3*(vertexCount - 2)}; + generateTriangleFanIndicesInto(vertexCount, indices); + return indices; +} + +}} diff --git a/src/Magnum/MeshTools/GenerateIndices.h b/src/Magnum/MeshTools/GenerateIndices.h new file mode 100644 index 000000000..28d981723 --- /dev/null +++ b/src/Magnum/MeshTools/GenerateIndices.h @@ -0,0 +1,132 @@ +#ifndef Magnum_MeshTools_GenerateIndices_h +#define Magnum_MeshTools_GenerateIndices_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Function @ref Magnum::MeshTools::generateLineStripIndices(), @ref Magnum::MeshTools::generateLineStripIndicesInto(), @ref Magnum::MeshTools::generateLineLoopIndices(), @ref Magnum::MeshTools::generateLineLoopIndicesInto(), @ref Magnum::MeshTools::generateTriangleStripIndices(), @ref Magnum::MeshTools::generateTriangleStripIndicesInto(), @ref Magnum::MeshTools::generateTriangleFanIndices(), @ref Magnum::MeshTools::generateTriangleFanIndicesInto() + * @m_since_latest + */ + +#include "Magnum/Magnum.h" +#include "Magnum/MeshTools/visibility.h" + +namespace Magnum { namespace MeshTools { + +/** +@brief Create index buffer for a line strip primitive +@m_since_latest + +Can be used to convert a @ref MeshPrimitive::LineStrip mesh to +@ref MeshPrimitive::Lines. The @p vertexCount is expected to be at least +@cpp 2 @ce. Primitive restart is not supported. +@see @ref generateLineStripIndicesInto(), @ref generateLineLoopIndices(), + @ref generateTriangleStripIndices(), @ref generateTriangleFanIndices() +*/ +MAGNUM_MESHTOOLS_EXPORT Containers::Array generateLineStripIndices(UnsignedInt vertexCount); + +/** +@brief Create index buffer for a line strip primitive into an existing array +@m_since_latest + +A variant of @ref generateLineStripIndicesInto() that fills existing memory +instead of allocating a new array. The @p vertexCount is expected to be at +least @cpp 2 @ce, the @p indices array is expected to have a size of +@cpp 2*(vertexCount - 1) @ce. Primitive restart is not supported. +*/ +MAGNUM_MESHTOOLS_EXPORT void generateLineStripIndicesInto(UnsignedInt vertexCount, const Containers::StridedArrayView1D& indices); + +/** +@brief Create index buffer for a line loop primitive +@m_since_latest + +Can be used to convert a @ref MeshPrimitive::LineLoop mesh to +@ref MeshPrimitive::Lines. The @p vertexCount is expected to be at least +@cpp 2 @ce. Primitive restart is not supported. +@see @ref generateLineLoopIndicesInto(), @ref generateLineStripIndices(), + @ref generateTriangleStripIndices(), @ref generateTriangleFanIndices() +*/ +MAGNUM_MESHTOOLS_EXPORT Containers::Array generateLineLoopIndices(UnsignedInt vertexCount); + +/** +@brief Create index buffer for a line loop primitive into an existing array +@m_since_latest + +A variant of @ref generateLineLoopIndicesInto() that fills existing memory +instead of allocating a new array. The @p vertexCount is expected to be at +least @cpp 2 @ce, the @p indices array is expected to have a size of +@cpp 2*vertexCount @ce. Primitive restart is not supported. +*/ +MAGNUM_MESHTOOLS_EXPORT void generateLineLoopIndicesInto(UnsignedInt vertexCount, const Containers::StridedArrayView1D& into); + +/** +@brief Create index buffer for a triangle strip primitive +@m_since_latest + +Can be used to convert a @ref MeshPrimitive::TriangleStrip mesh to +@ref MeshPrimitive::Triangles. The @p vertexCount is expected to be at least +@cpp 3 @ce. Primitive restart is not supported. +@see @ref generateTriangleStripIndicesInto(), @ref generateLineStripIndices(), + @ref generateLineLoopIndices(), @ref generateTriangleFanIndices() +*/ +MAGNUM_MESHTOOLS_EXPORT Containers::Array generateTriangleStripIndices(UnsignedInt vertexCount); + +/** +@brief Create index buffer for a triangle strip primitive into an existing array +@m_since_latest + +A variant of @ref generateTriangleStripIndicesInto() that fills existing memory +instead of allocating a new array. The @p vertexCount is expected to be at +least @cpp 3 @ce, the @p indices array is expected to have a size of +@cpp 3*(vertexCount - 2) @ce. Primitive restart is not supported. +*/ +MAGNUM_MESHTOOLS_EXPORT void generateTriangleStripIndicesInto(UnsignedInt vertexCount, const Containers::StridedArrayView1D& into); + +/** +@brief Create index buffer for a triangle fan primitive +@m_since_latest + +Can be used to convert a @ref MeshPrimitive::TriangleFan mesh to +@ref MeshPrimitive::Triangles. The @p vertexCount is expected to be at least +@cpp 3 @ce. Primitive restart is not supported. +@see @ref generateTriangleFanIndicesInto(), @ref generateLineStripIndices(), + @ref generateLineLoopIndices(), @ref generateTriangleStripIndices() +*/ +MAGNUM_MESHTOOLS_EXPORT Containers::Array generateTriangleFanIndices(UnsignedInt vertexCount); + +/** +@brief Create index buffer for a triangle fan primitive into an existing array +@m_since_latest + +A variant of @ref generateTriangleFanIndicesInto() that fills existing memory +instead of allocating a new array. The @p vertexCount is expected to be at +least @cpp 3 @ce, the @p indices array is expected to have a size of +@cpp 3*(vertexCount - 2) @ce. Primitive restart is not supported. +*/ +MAGNUM_MESHTOOLS_EXPORT void generateTriangleFanIndicesInto(UnsignedInt vertexCount, const Containers::StridedArrayView1D& into); + +}} + +#endif diff --git a/src/Magnum/MeshTools/Test/CMakeLists.txt b/src/Magnum/MeshTools/Test/CMakeLists.txt index 8f1913b8b..ae64ea45f 100644 --- a/src/Magnum/MeshTools/Test/CMakeLists.txt +++ b/src/Magnum/MeshTools/Test/CMakeLists.txt @@ -28,6 +28,7 @@ corrade_add_test(MeshToolsCompressIndicesTest CompressIndicesTest.cpp LIBRARIES corrade_add_test(MeshToolsConcatenateTest ConcatenateTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsDuplicateTest DuplicateTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsFlipNormalsTest FlipNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib) +corrade_add_test(MeshToolsGenerateIndicesTest GenerateIndicesTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsGenerateNormalsTest GenerateNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib MagnumPrimitives) corrade_add_test(MeshToolsInterleaveTest InterleaveTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsRemoveDuplicatesTest RemoveDuplicatesTest.cpp LIBRARIES MagnumMeshToolsTestLib) @@ -51,6 +52,7 @@ set_target_properties( MeshToolsConcatenateTest MeshToolsDuplicateTest MeshToolsFlipNormalsTest + MeshToolsGenerateIndicesTest MeshToolsGenerateNormalsTest MeshToolsInterleaveTest MeshToolsRemoveDuplicatesTest diff --git a/src/Magnum/MeshTools/Test/GenerateIndicesTest.cpp b/src/Magnum/MeshTools/Test/GenerateIndicesTest.cpp new file mode 100644 index 000000000..14b038da2 --- /dev/null +++ b/src/Magnum/MeshTools/Test/GenerateIndicesTest.cpp @@ -0,0 +1,264 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include + +#include "Magnum/MeshTools/GenerateIndices.h" + +namespace Magnum { namespace MeshTools { namespace Test { namespace { + +struct GenerateIndicesTest: TestSuite::Tester { + explicit GenerateIndicesTest(); + + void generateLineStripIndices(); + void generateLineStripIndicesWrongVertexCount(); + void generateLineStripIndicesIntoWrongSize(); + + void generateLineLoopIndices(); + void generateLineLoopIndicesWrongVertexCount(); + void generateLineLoopIndicesIntoWrongSize(); + + void generateTriangleStripIndices(); + void generateTriangleStripIndicesWrongVertexCount(); + void generateTriangleStripIndicesIntoWrongSize(); + + void generateTriangleFanIndices(); + void generateTriangleFanIndicesWrongVertexCount(); + void generateTriangleFanIndicesIntoWrongSize(); +}; + +GenerateIndicesTest::GenerateIndicesTest() { + addTests({&GenerateIndicesTest::generateLineStripIndices, + &GenerateIndicesTest::generateLineStripIndicesWrongVertexCount, + &GenerateIndicesTest::generateLineStripIndicesIntoWrongSize, + + &GenerateIndicesTest::generateLineLoopIndices, + &GenerateIndicesTest::generateLineLoopIndicesWrongVertexCount, + &GenerateIndicesTest::generateLineLoopIndicesIntoWrongSize, + + &GenerateIndicesTest::generateTriangleStripIndices, + &GenerateIndicesTest::generateTriangleStripIndicesWrongVertexCount, + &GenerateIndicesTest::generateTriangleStripIndicesIntoWrongSize, + + &GenerateIndicesTest::generateTriangleFanIndices, + &GenerateIndicesTest::generateTriangleFanIndicesWrongVertexCount, + &GenerateIndicesTest::generateTriangleFanIndicesIntoWrongSize}); +} + +void GenerateIndicesTest::generateLineStripIndices() { + /* Minimal input */ + CORRADE_COMPARE_AS(MeshTools::generateLineStripIndices(2), + Containers::arrayView({ + 0, 1 + }), TestSuite::Compare::Container); + + /* Odd */ + CORRADE_COMPARE_AS(MeshTools::generateLineStripIndices(5), + Containers::arrayView({ + 0, 1, + 1, 2, + 2, 3, + 3, 4 + }), TestSuite::Compare::Container); + + /* Even */ + CORRADE_COMPARE_AS(MeshTools::generateLineStripIndices(6), + Containers::arrayView({ + 0, 1, + 1, 2, + 2, 3, + 3, 4, + 4, 5 + }), TestSuite::Compare::Container); +} + +void GenerateIndicesTest::generateLineStripIndicesWrongVertexCount() { + std::ostringstream out; + Error redirectError{&out}; + MeshTools::generateLineStripIndicesInto(1, nullptr); + CORRADE_COMPARE(out.str(), + "MeshTools::generateLineStripIndicesInto(): expected at least two vertices, got 1\n"); +} + +void GenerateIndicesTest::generateLineStripIndicesIntoWrongSize() { + UnsignedInt indices[7]; + + std::ostringstream out; + Error redirectError{&out}; + MeshTools::generateLineStripIndicesInto(5, indices); + CORRADE_COMPARE(out.str(), + "MeshTools::generateLineStripIndicesInto(): bad output size, expected 8 but got 7\n"); +} + +void GenerateIndicesTest::generateLineLoopIndices() { + /* Minimal input */ + CORRADE_COMPARE_AS(MeshTools::generateLineLoopIndices(2), + Containers::arrayView({ + 0, 1, + 1, 0 + }), TestSuite::Compare::Container); + + /* Odd */ + CORRADE_COMPARE_AS(MeshTools::generateLineLoopIndices(5), + Containers::arrayView({ + 0, 1, + 1, 2, + 2, 3, + 3, 4, + 4, 0 + }), TestSuite::Compare::Container); + + /* Even */ + CORRADE_COMPARE_AS(MeshTools::generateLineLoopIndices(6), + Containers::arrayView({ + 0, 1, + 1, 2, + 2, 3, + 3, 4, + 4, 5, + 5, 0 + }), TestSuite::Compare::Container); +} + +void GenerateIndicesTest::generateLineLoopIndicesWrongVertexCount() { + std::ostringstream out; + Error redirectError{&out}; + MeshTools::generateLineLoopIndicesInto(1, nullptr); + CORRADE_COMPARE(out.str(), + "MeshTools::generateLineLoopIndicesInto(): expected at least two vertices, got 1\n"); +} + +void GenerateIndicesTest::generateLineLoopIndicesIntoWrongSize() { + UnsignedInt indices[9]; + + std::ostringstream out; + Error redirectError{&out}; + MeshTools::generateLineLoopIndicesInto(5, indices); + CORRADE_COMPARE(out.str(), + "MeshTools::generateLineLoopIndicesInto(): bad output size, expected 10 but got 9\n"); +} + +void GenerateIndicesTest::generateTriangleStripIndices() { + /* Minimal input */ + CORRADE_COMPARE_AS(MeshTools::generateTriangleStripIndices(3), + Containers::arrayView({ + 0, 1, 2 + }), TestSuite::Compare::Container); + + /* Odd */ + CORRADE_COMPARE_AS(MeshTools::generateTriangleStripIndices(7), + Containers::arrayView({ + 0, 1, 2, + 2, 1, 3, /* Reversed */ + 2, 3, 4, + 4, 3, 5, /* Reversed */ + 4, 5, 6 + }), TestSuite::Compare::Container); + + /* Even */ + CORRADE_COMPARE_AS(MeshTools::generateTriangleStripIndices(8), + Containers::arrayView({ + 0, 1, 2, + 2, 1, 3, /* Reversed */ + 2, 3, 4, + 4, 3, 5, /* Reversed */ + 4, 5, 6, + 6, 5, 7 /* Reversed */ + }), TestSuite::Compare::Container); +} + +void GenerateIndicesTest::generateTriangleStripIndicesWrongVertexCount() { + std::ostringstream out; + Error redirectError{&out}; + MeshTools::generateTriangleStripIndicesInto(2, nullptr); + CORRADE_COMPARE(out.str(), + "MeshTools::generateTriangleStripIndicesInto(): expected at least three vertices, got 2\n"); +} + +void GenerateIndicesTest::generateTriangleStripIndicesIntoWrongSize() { + UnsignedInt indices[8]; + + std::ostringstream out; + Error redirectError{&out}; + MeshTools::generateTriangleStripIndicesInto(5, indices); + CORRADE_COMPARE(out.str(), + "MeshTools::generateTriangleStripIndicesInto(): bad output size, expected 9 but got 8\n"); +} + +void GenerateIndicesTest::generateTriangleFanIndices() { + /* Minimal input */ + CORRADE_COMPARE_AS(MeshTools::generateTriangleFanIndices(3), + Containers::arrayView({ + 0, 1, 2 + }), TestSuite::Compare::Container); + + /* Odd */ + CORRADE_COMPARE_AS(MeshTools::generateTriangleFanIndices(7), + Containers::arrayView({ + 0, 1, 2, + 0, 2, 3, + 0, 3, 4, + 0, 4, 5, + 0, 5, 6 + }), TestSuite::Compare::Container); + + /* Even */ + CORRADE_COMPARE_AS(MeshTools::generateTriangleFanIndices(8), + Containers::arrayView({ + 0, 1, 2, + 0, 2, 3, + 0, 3, 4, + 0, 4, 5, + 0, 5, 6, + 0, 6, 7 + }), TestSuite::Compare::Container); +} + +void GenerateIndicesTest::generateTriangleFanIndicesWrongVertexCount() { + std::ostringstream out; + Error redirectError{&out}; + MeshTools::generateTriangleFanIndicesInto(2, nullptr); + CORRADE_COMPARE(out.str(), + "MeshTools::generateTriangleFanIndicesInto(): expected at least three vertices, got 2\n"); +} + +void GenerateIndicesTest::generateTriangleFanIndicesIntoWrongSize() { + UnsignedInt indices[8]; + + std::ostringstream out; + Error redirectError{&out}; + MeshTools::generateTriangleFanIndicesInto(5, indices); + CORRADE_COMPARE(out.str(), + "MeshTools::generateTriangleFanIndicesInto(): bad output size, expected 9 but got 8\n"); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::MeshTools::Test::GenerateIndicesTest)