diff --git a/doc/changelog.dox b/doc/changelog.dox index c2d3289a0..737b98314 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -151,6 +151,8 @@ See also: into per-vertex - New @ref MeshTools::concatenate() and @ref MeshTools::concatenateInto() tool for batching multiple generic meshes together +- @ref MeshTools::primitiveCount() for calculating number of generated + primitives for a particular primitive type - New family of @ref MeshTools::generateLineStripIndices(), @ref MeshTools::generateLineLoopIndices(), @ref MeshTools::generateTriangleStripIndices() and diff --git a/src/Magnum/MeshTools/GenerateIndices.cpp b/src/Magnum/MeshTools/GenerateIndices.cpp index 25ca1d63b..02bc409fb 100644 --- a/src/Magnum/MeshTools/GenerateIndices.cpp +++ b/src/Magnum/MeshTools/GenerateIndices.cpp @@ -33,6 +33,29 @@ namespace Magnum { namespace MeshTools { +UnsignedInt primitiveCount(const MeshPrimitive primitive, const UnsignedInt elementCount) { + if(primitive == MeshPrimitive::Points || + primitive == MeshPrimitive::Edges || + primitive == MeshPrimitive::Faces || + primitive == MeshPrimitive::Instances) + return elementCount; + if(primitive == MeshPrimitive::Lines) + return elementCount/2; + if(primitive == MeshPrimitive::LineStrip) + return elementCount < 1 ? 0 : elementCount - 1; + if(primitive == MeshPrimitive::LineLoop) + /* For a single element it'll define a degenerate line, which + technically still *is* a primitive */ + return elementCount; + if(primitive == MeshPrimitive::Triangles) + return elementCount/3; + if(primitive == MeshPrimitive::TriangleStrip || + primitive == MeshPrimitive::TriangleFan) + return elementCount < 2 ? 0 : elementCount - 2; + CORRADE_ASSERT(false, + "MeshTools::primitiveCount(): invalid primitive" << primitive, {}); +} + void generateLineStripIndicesInto(const UnsignedInt vertexCount, const Containers::StridedArrayView1D& indices) { CORRADE_ASSERT(vertexCount >= 2, "MeshTools::generateLineStripIndicesInto(): expected at least two vertices, got" << vertexCount, ); diff --git a/src/Magnum/MeshTools/GenerateIndices.h b/src/Magnum/MeshTools/GenerateIndices.h index ca4a1edda..427436e86 100644 --- a/src/Magnum/MeshTools/GenerateIndices.h +++ b/src/Magnum/MeshTools/GenerateIndices.h @@ -26,7 +26,7 @@ */ /** @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(), @ref Magnum::MeshTools::generateIndices() + * @brief Function @ref Magnum::MeshTools::primitiveCount(), @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(), @ref Magnum::MeshTools::generateIndices() * @m_since_latest */ @@ -36,6 +36,18 @@ namespace Magnum { namespace MeshTools { +/** +@brief Actual primitive count for given primitive type and element count +@m_since_latest + +Returns how many primitives is generated for given @p primitive and +@p elementCount, for example for @ref MeshPrimitive::Triangles returns +@cpp elementCount/3 @ce. Expects that @p primitive is valid, return value is +rounded down if there's not enough elements for given primitive type (so for +14 vertices you get just 4 triangles, for example). +*/ +MAGNUM_MESHTOOLS_EXPORT UnsignedInt primitiveCount(MeshPrimitive primitive, UnsignedInt elementCount); + /** @brief Create index buffer for a line strip primitive @m_since_latest diff --git a/src/Magnum/MeshTools/Test/GenerateIndicesTest.cpp b/src/Magnum/MeshTools/Test/GenerateIndicesTest.cpp index 4042eef6f..bf8ed0a6b 100644 --- a/src/Magnum/MeshTools/Test/GenerateIndicesTest.cpp +++ b/src/Magnum/MeshTools/Test/GenerateIndicesTest.cpp @@ -39,6 +39,9 @@ namespace Magnum { namespace MeshTools { namespace Test { namespace { struct GenerateIndicesTest: TestSuite::Tester { explicit GenerateIndicesTest(); + void primitiveCount(); + void primitiveCountInvalidPrimitive(); + void generateLineStripIndices(); void generateLineStripIndicesWrongVertexCount(); void generateLineStripIndicesIntoWrongSize(); @@ -91,7 +94,10 @@ const struct { }; GenerateIndicesTest::GenerateIndicesTest() { - addTests({&GenerateIndicesTest::generateLineStripIndices, + addTests({&GenerateIndicesTest::primitiveCount, + &GenerateIndicesTest::primitiveCountInvalidPrimitive, + + &GenerateIndicesTest::generateLineStripIndices, &GenerateIndicesTest::generateLineStripIndicesWrongVertexCount, &GenerateIndicesTest::generateLineStripIndicesIntoWrongSize, @@ -115,6 +121,41 @@ GenerateIndicesTest::GenerateIndicesTest() { &GenerateIndicesTest::generateIndicesMeshDataInvalidPrimitive}); } +void GenerateIndicesTest::primitiveCount() { + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::Points, 42), 42); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::Instances, 13), 13); + + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::Lines, 4), 2); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::Lines, 5), 2); + + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::LineStrip, 1), 0); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::LineStrip, 2), 1); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::LineStrip, 4), 3); + + /* This is a degenerate line, which technically still is a primitive */ + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::LineLoop, 1), 1); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::LineLoop, 2), 2); + + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::Triangles, 2), 0); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::Triangles, 3), 1); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::Triangles, 6), 2); + + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::TriangleStrip, 2), 0); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::TriangleFan, 2), 0); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::TriangleStrip, 3), 1); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::TriangleFan, 3), 1); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::TriangleStrip, 7), 5); + CORRADE_COMPARE(MeshTools::primitiveCount(MeshPrimitive::TriangleFan, 7), 5); +} + +void GenerateIndicesTest::primitiveCountInvalidPrimitive() { + std::ostringstream out; + Error redirectError{&out}; + MeshTools::primitiveCount(MeshPrimitive(0xdead), 2); + CORRADE_COMPARE(out.str(), + "MeshTools::primitiveCount(): invalid primitive MeshPrimitive(0xdead)\n"); +} + void GenerateIndicesTest::generateLineStripIndices() { /* Minimal input */ CORRADE_COMPARE_AS(MeshTools::generateLineStripIndices(2),