From ae8db0471f0b6ab1cecc58f098d4a1c5a63db444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 9 Mar 2018 16:06:09 +0100 Subject: [PATCH] Primitives: 3D circle primitive. --- doc/changelog.dox | 5 ++ src/Magnum/Primitives/Circle.cpp | 44 ++++++++++++++++- src/Magnum/Primitives/Circle.h | 26 ++++++++-- src/Magnum/Primitives/Test/CircleTest.cpp | 59 ++++++++++++++++++++--- 4 files changed, 123 insertions(+), 11 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index e05be33db..5a06da54b 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -51,6 +51,11 @@ See also: @webgl_extension{WEBGL,color_buffer_float}, @webgl_extension{EXT,color_buffer_float} +@subsubsection changelog-latest-new-primitives Primitives library + +- New @ref Primitives::circle3DSolid() and @ref Primitives::circle3DWireframe() + primitives + @subsection changelog-latest-deprecated Deprecated APIs - Class @cpp Primitives::Capsule2D @ce and @cpp Primitives::Capsule3D @ce is diff --git a/src/Magnum/Primitives/Circle.cpp b/src/Magnum/Primitives/Circle.cpp index 272d38778..da62e2cdd 100644 --- a/src/Magnum/Primitives/Circle.cpp +++ b/src/Magnum/Primitives/Circle.cpp @@ -29,6 +29,7 @@ #include "Magnum/Math/Color.h" #include "Magnum/Mesh.h" #include "Magnum/Trade/MeshData2D.h" +#include "Magnum/Trade/MeshData3D.h" namespace Magnum { namespace Primitives { @@ -37,7 +38,7 @@ Trade::MeshData2D circle2DSolid(const UnsignedInt segments) { (Trade::MeshData2D{MeshPrimitive::TriangleFan, {}, {}, {}, {}, nullptr})); std::vector positions; - positions.reserve(segments+1); + positions.reserve(segments + 2); /* Central point */ positions.emplace_back(); @@ -70,6 +71,47 @@ Trade::MeshData2D circle2DWireframe(const UnsignedInt segments) { return Trade::MeshData2D{MeshPrimitive::LineLoop, {}, {std::move(positions)}, {}, {}, nullptr}; } +Trade::MeshData3D circle3DSolid(const UnsignedInt segments) { + CORRADE_ASSERT(segments >= 3, "Primitives::circle3DSolid(): segments must be >= 3", + (Trade::MeshData3D{MeshPrimitive::TriangleFan, {}, {}, {}, {}, {}, nullptr})); + + std::vector positions; + positions.reserve(segments + 2); + + /* Central point */ + positions.emplace_back(); + + /* Points on circle. The first/last point is here twice to close the circle + properly. */ + const Rad angleIncrement(Constants::tau()/segments); + for(UnsignedInt i = 0; i != segments + 1; ++i) { + const Rad angle(Float(i)*angleIncrement); + positions.emplace_back(Math::cos(angle), Math::sin(angle), 0.0f); + } + + /* Normals. All pointing in the same direction. */ + std::vector normals{segments + 2, Vector3::zAxis(1.0f)}; + + return Trade::MeshData3D{MeshPrimitive::TriangleFan, {}, {std::move(positions)}, {std::move(normals)}, {}, {}, nullptr}; +} + +Trade::MeshData3D circle3DWireframe(const UnsignedInt segments) { + CORRADE_ASSERT(segments >= 3, "Primitives::circle3DWireframe(): segments must be >= 3", + (Trade::MeshData3D{MeshPrimitive::LineLoop, {}, {}, {}, {}, {}, nullptr})); + + std::vector positions; + positions.reserve(segments); + + /* Points on circle */ + const Rad angleIncrement(Constants::tau()/segments); + for(UnsignedInt i = 0; i != segments; ++i) { + const Rad angle(Float(i)*angleIncrement); + positions.emplace_back(Math::cos(angle), Math::sin(angle), 0.0f); + } + + return Trade::MeshData3D{MeshPrimitive::LineLoop, {}, {std::move(positions)}, {}, {}, {}, nullptr}; +} + #ifdef MAGNUM_BUILD_DEPRECATED Trade::MeshData2D Circle::solid(const UnsignedInt segments) { return circle2DSolid(segments); diff --git a/src/Magnum/Primitives/Circle.h b/src/Magnum/Primitives/Circle.h index c9941ac4e..b94b75c6a 100644 --- a/src/Magnum/Primitives/Circle.h +++ b/src/Magnum/Primitives/Circle.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Function @ref Magnum::Primitives::circle2DSolid(), @ref Magnum::Primitives::circle2DWireframe() + * @brief Function @ref Magnum::Primitives::circle2DSolid(), @ref Magnum::Primitives::circle2DWireframe(), @ref Magnum::Primitives::circle3DSolid(), @ref Magnum::Primitives::circle3DWireframe() */ #include "Magnum/Primitives/visibility.h" @@ -43,7 +43,7 @@ namespace Magnum { namespace Primitives { @param segments Number of segments. Must be greater or equal to @cpp 3 @ce. Circle with radius @cpp 1.0f @ce. Non-indexed @ref MeshPrimitive::TriangleFan. -@see @ref circle2DWireframe() +@see @ref circle2DWireframe(), @ref circle3DSolid() */ MAGNUM_PRIMITIVES_EXPORT Trade::MeshData2D circle2DSolid(UnsignedInt segments); @@ -52,7 +52,7 @@ MAGNUM_PRIMITIVES_EXPORT Trade::MeshData2D circle2DSolid(UnsignedInt segments); @param segments Number of segments. Must be greater or equal to @cpp 3 @ce. Circle with radius @cpp 1.0f @ce. Non-indexed @ref MeshPrimitive::LineLoop. -@see @ref circle2DSolid() +@see @ref circle2DSolid(), @ref circle3DWireframe() */ MAGNUM_PRIMITIVES_EXPORT Trade::MeshData2D circle2DWireframe(UnsignedInt segments); @@ -74,6 +74,26 @@ struct MAGNUM_PRIMITIVES_EXPORT Circle { }; #endif +/** +@brief Solid 3D circle +@param segments Number of segments. Must be greater or equal to @cpp 3 @ce. + +Circle on the XY plane with radius @cpp 1.0f @ce. Non-indexed +@ref MeshPrimitive::TriangleFan with normals in positive Z direction. +@see @ref circle3DWireframe(), @ref circle2DSolid() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D circle3DSolid(UnsignedInt segments); + +/** +@brief Wireframe 3D circle +@param segments Number of segments. Must be greater or equal to @cpp 3 @ce. + +Circle on the XY plane with radius @cpp 1.0f @ce. Non-indexed +@ref MeshPrimitive::LineLoop. +@see @ref circle2DSolid(), @ref circle3DWireframe() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D circle3DWireframe(UnsignedInt segments); + }} #endif diff --git a/src/Magnum/Primitives/Test/CircleTest.cpp b/src/Magnum/Primitives/Test/CircleTest.cpp index 51a7aea16..b04c86dfa 100644 --- a/src/Magnum/Primitives/Test/CircleTest.cpp +++ b/src/Magnum/Primitives/Test/CircleTest.cpp @@ -26,25 +26,30 @@ #include #include "Magnum/Mesh.h" -#include "Magnum/Math/Vector2.h" +#include "Magnum/Math/Vector3.h" #include "Magnum/Primitives/Circle.h" #include "Magnum/Trade/MeshData2D.h" +#include "Magnum/Trade/MeshData3D.h" namespace Magnum { namespace Primitives { namespace Test { struct CircleTest: TestSuite::Tester { explicit CircleTest(); - void solid(); - void wireframe(); + void solid2D(); + void solid3D(); + void wireframe2D(); + void wireframe3D(); }; CircleTest::CircleTest() { - addTests({&CircleTest::solid, - &CircleTest::wireframe}); + addTests({&CircleTest::solid2D, + &CircleTest::solid3D, + &CircleTest::wireframe2D, + &CircleTest::wireframe3D}); } -void CircleTest::solid() { +void CircleTest::solid2D() { Trade::MeshData2D circle = Primitives::circle2DSolid(8); CORRADE_VERIFY(!circle.isIndexed()); @@ -59,7 +64,34 @@ void CircleTest::solid() { })); } -void CircleTest::wireframe() { +void CircleTest::solid3D() { + Trade::MeshData3D circle = Primitives::circle3DSolid(8); + + CORRADE_VERIFY(!circle.isIndexed()); + CORRADE_COMPARE(circle.primitive(), MeshPrimitive::TriangleFan); + CORRADE_COMPARE(circle.positions(0), (std::vector{ + { 0.0f, 0.0f, 0.0f}, + { 1.0f, 0.0f, 0.0f}, { Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f, 0.0f}, + { 0.0f, 1.0f, 0.0f}, {-Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, {-Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f, 0.0f}, + { 0.0f, -1.0f, 0.0f}, { Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f, 0.0f}, + { 1.0f, 0.0f, 0.0f} + })); + CORRADE_COMPARE(circle.normals(0), (std::vector{ + { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f, 1.0f} + })); +} + +void CircleTest::wireframe2D() { Trade::MeshData2D circle = Primitives::circle2DWireframe(8); CORRADE_VERIFY(!circle.isIndexed()); @@ -72,6 +104,19 @@ void CircleTest::wireframe() { })); } +void CircleTest::wireframe3D() { + Trade::MeshData3D circle = Primitives::circle3DWireframe(8); + + CORRADE_VERIFY(!circle.isIndexed()); + CORRADE_COMPARE(circle.primitive(), MeshPrimitive::LineLoop); + CORRADE_COMPARE(circle.positions(0), (std::vector{ + { 1.0f, 0.0f, 0.0f}, { Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f, 0.0f}, + { 0.0f, 1.0f, 0.0f}, {-Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, {-Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f, 0.0f}, + { 0.0f, -1.0f, 0.0f}, { Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f, 0.0f} + })); +} + }}} CORRADE_TEST_MAIN(Magnum::Primitives::Test::CircleTest)