From 56cade15ca512d9b5a3b010559ea497721a3fe7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 16 Apr 2020 17:28:22 +0200 Subject: [PATCH] Primitives: added a wireframe icosphere. --- doc/changelog.dox | 1 + doc/generated/primitives.cpp | 6 ++ doc/primitives-icospherewireframe.png | Bin 0 -> 10150 bytes src/Magnum/Primitives/Icosphere.cpp | 76 ++++++++++++++----- src/Magnum/Primitives/Icosphere.h | 23 +++++- src/Magnum/Primitives/Test/IcosphereTest.cpp | 16 +++- 6 files changed, 100 insertions(+), 22 deletions(-) create mode 100644 doc/primitives-icospherewireframe.png diff --git a/doc/changelog.dox b/doc/changelog.dox index 24f04742a..15763d611 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -210,6 +210,7 @@ See also: @ref Primitives::coneSolid(), @ref Primitives::cylinderSolid(), @ref Primitives::grid3DSolid(), @ref Primitives::planeSolid() and @ref Primitives::uvSphereSolid() can now have tangents as well +- Added @ref Primitives::icosphereWireframe() @subsubsection changelog-latest-new-scenegraph SceneGraph library diff --git a/doc/generated/primitives.cpp b/doc/generated/primitives.cpp index 166253984..7f1bb57a9 100644 --- a/doc/generated/primitives.cpp +++ b/doc/generated/primitives.cpp @@ -108,6 +108,7 @@ struct PrimitiveVisualizer: Platform::WindowlessApplication { std::pair cubeWireframe(); std::pair cylinderWireframe(); std::pair grid3DWireframe(); + std::pair icosphereWireframe(); std::pair line3D(); std::pair planeWireframe(); std::pair uvSphereWireframe(); @@ -257,6 +258,7 @@ int PrimitiveVisualizer::exec() { &PrimitiveVisualizer::cubeWireframe, &PrimitiveVisualizer::cylinderWireframe, &PrimitiveVisualizer::grid3DWireframe, + &PrimitiveVisualizer::icosphereWireframe, &PrimitiveVisualizer::line3D, &PrimitiveVisualizer::planeWireframe, &PrimitiveVisualizer::uvSphereWireframe}) @@ -497,6 +499,10 @@ std::pair PrimitiveVisualizer::grid3DWireframe() { return {Primitives::grid3DWireframe({5, 3}), "grid3dwireframe.png"}; } +std::pair PrimitiveVisualizer::icosphereWireframe() { + return {Primitives::icosphereWireframe(), "icospherewireframe.png"}; +} + std::pair PrimitiveVisualizer::line3D() { Trade::MeshData line = Primitives::line3D(); MeshTools::transformPointsInPlace(Matrix4::translation(Vector3::xAxis(-1.0f))*Matrix4::scaling(Vector3::xScale(2.0f)), diff --git a/doc/primitives-icospherewireframe.png b/doc/primitives-icospherewireframe.png new file mode 100644 index 0000000000000000000000000000000000000000..07468a5a95f1930e48f3a45f41883f914eb2e2e1 GIT binary patch literal 10150 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 WmesZK%_;X}-QcFFZk3MH^Zx<&${a8N literal 0 HcmV?d00001 diff --git a/src/Magnum/Primitives/Icosphere.cpp b/src/Magnum/Primitives/Icosphere.cpp index 7a1f504be..0fd6ff1af 100644 --- a/src/Magnum/Primitives/Icosphere.cpp +++ b/src/Magnum/Primitives/Icosphere.cpp @@ -42,16 +42,19 @@ constexpr UnsignedInt Indices[]{ 3, 4, 5, 4, 3, 8, 6, 5, 11, + 5, 6, 10, 9, 10, 2, 10, 9, 3, 7, 8, 9, 8, 7, 0, + 11, 0, 1, 0, 11, 4, 6, 2, 10, 1, 6, 11, 3, 5, 10, + 5, 4, 11, 2, 7, 9, 7, 1, 0, @@ -59,26 +62,30 @@ constexpr UnsignedInt Indices[]{ 4, 8, 0 }; -constexpr Vector3 Positions[]{ - {0.0f, -0.525731f, 0.850651f}, - {0.850651f, 0.0f, 0.525731f}, - {0.850651f, 0.0f, -0.525731f}, - {-0.850651f, 0.0f, -0.525731f}, - {-0.850651f, 0.0f, 0.525731f}, - {-0.525731f, 0.850651f, 0.0f}, - {0.525731f, 0.850651f, 0.0f}, - {0.525731f, -0.850651f, 0.0f}, - {-0.525731f, -0.850651f, 0.0f}, - {0.0f, -0.525731f, -0.850651f}, - {0.0f, 0.525731f, -0.850651f}, - {0.0f, 0.525731f, 0.850651f} +/* Can't be just an array of Vector3 because MSVC 2015 is special. See + Crosshair.cpp for details. */ +constexpr struct VertexSolidStrip { + Vector3 position; +} Vertices[]{ + {{0.0f, -0.525731f, 0.850651f}}, + {{0.850651f, 0.0f, 0.525731f}}, + {{0.850651f, 0.0f, -0.525731f}}, + {{-0.850651f, 0.0f, -0.525731f}}, + {{-0.850651f, 0.0f, 0.525731f}}, + {{-0.525731f, 0.850651f, 0.0f}}, + {{0.525731f, 0.850651f, 0.0f}}, + {{0.525731f, -0.850651f, 0.0f}}, + {{-0.525731f, -0.850651f, 0.0f}}, + {{0.0f, -0.525731f, -0.850651f}}, + {{0.0f, 0.525731f, -0.850651f}}, + {{0.0f, 0.525731f, 0.850651f}} }; } Trade::MeshData icosphereSolid(const UnsignedInt subdivisions) { const std::size_t indexCount = Containers::arraySize(Indices)*(1 << subdivisions*2); - const std::size_t vertexCount = Containers::arraySize(Positions) + ((indexCount - Containers::arraySize(Indices))/3); + const std::size_t vertexCount = Containers::arraySize(Vertices) + ((indexCount - Containers::arraySize(Indices))/3); Containers::Array indexData{indexCount*sizeof(UnsignedInt)}; auto indices = Containers::arrayCast(indexData); @@ -96,12 +103,12 @@ Trade::MeshData icosphereSolid(const UnsignedInt subdivisions) { { auto vertices = Containers::arrayCast(vertexData); Containers::StridedArrayView1D positions{vertices, &vertices[0].position, vertices.size(), sizeof(Vertex)}; - for(std::size_t i = 0; i != Containers::arraySize(Positions); ++i) - positions[i] = Positions[i]; + for(std::size_t i = 0; i != Containers::arraySize(Vertices); ++i) + positions[i] = Vertices[i].position; for(std::size_t i = 0; i != subdivisions; ++i) { const std::size_t iterationIndexCount = Containers::arraySize(Indices)*(1 << (i + 1)*2); - const std::size_t iterationVertexCount = Containers::arraySize(Positions) + ((iterationIndexCount - Containers::arraySize(Indices))/3); + const std::size_t iterationVertexCount = Containers::arraySize(Vertices) + ((iterationIndexCount - Containers::arraySize(Indices))/3); MeshTools::subdivideInPlace(indices.prefix(iterationIndexCount), positions.prefix(iterationVertexCount), [](const Vector3& a, const Vector3& b) { return (a+b).normalized(); }); @@ -125,4 +132,39 @@ Trade::MeshData icosphereSolid(const UnsignedInt subdivisions) { Trade::MeshAttributeData{Trade::MeshAttribute::Normal, normals}}}; } +namespace { + +/* Taking the above, converting each triangle to three lines and leaving out + the duplicates. Because each edge is shared by two triangles and there was + 20 triangles to begin with, there's 30 edges. */ +constexpr UnsignedInt IndicesWireframe[]{ + 1, 2, 2, 6, 6, 1, + 1, 7, 7, 2, + 3, 4, 4, 5, 5, 3, + 3, 8, 8, 4, + 6, 5, 5, 11, 11, 6, + + 6, 10, 10, 5, + 9, 10, 10, 2, 2, 9, + 9, 3, 3, 10, + 7, 8, 8, 9, 9, 7, + 7, 0, 0, 8, + + 11, 0, 0, 1, 1, 11, + 11, 4, 4, 0 +}; +constexpr Trade::MeshAttributeData AttributesWireframe[]{ + Trade::MeshAttributeData{Trade::MeshAttribute::Position, + Containers::stridedArrayView(Vertices, &Vertices[0].position, + Containers::arraySize(Vertices), sizeof(Vector3))} +}; + +} + +Trade::MeshData icosphereWireframe() { + return Trade::MeshData{MeshPrimitive::Lines, + {}, IndicesWireframe, Trade::MeshIndexData{IndicesWireframe}, + {}, Vertices, Trade::meshAttributeDataNonOwningArray(AttributesWireframe)}; +} + }} diff --git a/src/Magnum/Primitives/Icosphere.h b/src/Magnum/Primitives/Icosphere.h index 6ef178d77..3f4267e07 100644 --- a/src/Magnum/Primitives/Icosphere.h +++ b/src/Magnum/Primitives/Icosphere.h @@ -47,14 +47,29 @@ normals. The @p subdivisions parameter describes how many times is each icosphere triangle subdivided, recursively. Specifying @cpp 0 @ce will result in an -icosphere with 20 faces, saying @cpp 1 @ce will result in an icosphere with 80 -faces (each triangle subdivided into four smaller), saying @cpp 2 @ce will -result in 320 faces and so on. In particular, this is different from the -`subdivisions` parameter in @ref grid3DSolid() or @ref grid3DWireframe(). +icosphere with 12 vertices and 20 faces, saying @cpp 1 @ce will result in an +icosphere with 80 faces (each triangle subdivided into four smaller), saying +@cpp 2 @ce will result in 320 faces and so on. In particular, this is different +from the `subdivisions` parameter in @ref grid3DSolid() or @ref grid3DWireframe(). @see @ref uvSphereSolid(), @ref uvSphereWireframe() */ MAGNUM_PRIMITIVES_EXPORT Trade::MeshData icosphereSolid(UnsignedInt subdivisions); +/** +@brief Wireframe 3D icosphere +@m_since_latest + +Sphere of radius @cpp 1.0f @ce with 12 vertices and 30 edges, centered at +origin. @ref MeshPrimitive::Lines with @ref MeshIndexType::UnsignedShort +indices and @ref VertexFormat::Vector3 positions. The returned instance +references data stored in constant memory. + +@image html primitives-icospherewireframe.png width=256px + +@see @ref icosphereWireframe() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData icosphereWireframe(); + }} #endif diff --git a/src/Magnum/Primitives/Test/IcosphereTest.cpp b/src/Magnum/Primitives/Test/IcosphereTest.cpp index 87f59ca96..b6fd6b4b9 100644 --- a/src/Magnum/Primitives/Test/IcosphereTest.cpp +++ b/src/Magnum/Primitives/Test/IcosphereTest.cpp @@ -38,12 +38,16 @@ struct IcosphereTest: TestSuite::Tester { void count0(); void data1(); void count2(); + + void wireframe(); }; IcosphereTest::IcosphereTest() { addTests({&IcosphereTest::count0, &IcosphereTest::data1, - &IcosphereTest::count2}); + &IcosphereTest::count2, + + &IcosphereTest::wireframe}); } void IcosphereTest::count0() { @@ -146,6 +150,16 @@ void IcosphereTest::count2() { CORRADE_COMPARE(icosphere.attributeCount(), 2); } +void IcosphereTest::wireframe() { + Trade::MeshData icosphere = Primitives::icosphereWireframe(); + + CORRADE_COMPARE(icosphere.primitive(), MeshPrimitive::Lines); + CORRADE_VERIFY(icosphere.isIndexed()); + CORRADE_COMPARE(icosphere.indexCount(), 60); + CORRADE_COMPARE(icosphere.vertexCount(), 12); + CORRADE_COMPARE(icosphere.attributeCount(), 1); +} + }}}} CORRADE_TEST_MAIN(Magnum::Primitives::Test::IcosphereTest)