Browse Source

Primitives: added a wireframe icosphere.

catastrophic-cross
Vladimír Vondruš 6 years ago
parent
commit
56cade15ca
  1. 1
      doc/changelog.dox
  2. 6
      doc/generated/primitives.cpp
  3. BIN
      doc/primitives-icospherewireframe.png
  4. 76
      src/Magnum/Primitives/Icosphere.cpp
  5. 23
      src/Magnum/Primitives/Icosphere.h
  6. 16
      src/Magnum/Primitives/Test/IcosphereTest.cpp

1
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

6
doc/generated/primitives.cpp

@ -108,6 +108,7 @@ struct PrimitiveVisualizer: Platform::WindowlessApplication {
std::pair<Trade::MeshData, std::string> cubeWireframe();
std::pair<Trade::MeshData, std::string> cylinderWireframe();
std::pair<Trade::MeshData, std::string> grid3DWireframe();
std::pair<Trade::MeshData, std::string> icosphereWireframe();
std::pair<Trade::MeshData, std::string> line3D();
std::pair<Trade::MeshData, std::string> planeWireframe();
std::pair<Trade::MeshData, std::string> 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<Trade::MeshData, std::string> PrimitiveVisualizer::grid3DWireframe() {
return {Primitives::grid3DWireframe({5, 3}), "grid3dwireframe.png"};
}
std::pair<Trade::MeshData, std::string> PrimitiveVisualizer::icosphereWireframe() {
return {Primitives::icosphereWireframe(), "icospherewireframe.png"};
}
std::pair<Trade::MeshData, std::string> PrimitiveVisualizer::line3D() {
Trade::MeshData line = Primitives::line3D();
MeshTools::transformPointsInPlace(Matrix4::translation(Vector3::xAxis(-1.0f))*Matrix4::scaling(Vector3::xScale(2.0f)),

BIN
doc/primitives-icospherewireframe.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

76
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<char> indexData{indexCount*sizeof(UnsignedInt)};
auto indices = Containers::arrayCast<UnsignedInt>(indexData);
@ -96,12 +103,12 @@ Trade::MeshData icosphereSolid(const UnsignedInt subdivisions) {
{
auto vertices = Containers::arrayCast<Vertex>(vertexData);
Containers::StridedArrayView1D<Vector3> 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)};
}
}}

23
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

16
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)

Loading…
Cancel
Save