From 8c74f4b2dbfe9c2fb8ec3fa04cba3e85d189d6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 18 Mar 2018 18:38:47 +0100 Subject: [PATCH] Primitives: added grid3DSolid() and grid3DWireframe(). --- doc/changelog.dox | 3 +- doc/generated/primitives.cpp | 13 + doc/primitives-grid3dsolid.png | Bin 0 -> 22276 bytes doc/primitives-grid3dwireframe.png | Bin 0 -> 3577 bytes src/Magnum/Primitives/CMakeLists.txt | 2 + src/Magnum/Primitives/Grid.cpp | 108 +++++++ src/Magnum/Primitives/Grid.h | 101 ++++++ src/Magnum/Primitives/Icosphere.h | 6 + src/Magnum/Primitives/Test/CMakeLists.txt | 1 + src/Magnum/Primitives/Test/GridTest.cpp | 377 ++++++++++++++++++++++ 10 files changed, 610 insertions(+), 1 deletion(-) create mode 100644 doc/primitives-grid3dsolid.png create mode 100644 doc/primitives-grid3dwireframe.png create mode 100644 src/Magnum/Primitives/Grid.cpp create mode 100644 src/Magnum/Primitives/Grid.h create mode 100644 src/Magnum/Primitives/Test/GridTest.cpp diff --git a/doc/changelog.dox b/doc/changelog.dox index 306f6df1a..61646e7cb 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -66,7 +66,8 @@ See also: @subsubsection changelog-latest-new-primitives Primitives library - New @ref Primitives::circle3DSolid(), @ref Primitives::circle3DWireframe(), - @ref Primitives::coneSolid() and @ref Primitives::coneWireframe() + @ref Primitives::coneSolid(), @ref Primitives::coneWireframe(), + @ref Primitives::grid3DSolid() and @ref Primitives::grid3DWireframe() primitives @subsection changelog-latest-bugfixes Bug fixes diff --git a/doc/generated/primitives.cpp b/doc/generated/primitives.cpp index 0b1fee72c..a0e191cab 100644 --- a/doc/generated/primitives.cpp +++ b/doc/generated/primitives.cpp @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,7 @@ struct PrimitiveVisualizer: Platform::WindowlessApplication { std::pair coneWireframe(); std::pair cubeWireframe(); std::pair cylinderWireframe(); + std::pair grid3DWireframe(); std::pair line3D(); std::pair planeWireframe(); std::pair uvSphereWireframe(); @@ -108,6 +110,7 @@ struct PrimitiveVisualizer: Platform::WindowlessApplication { std::pair coneSolid(); std::pair cubeSolid(); std::pair cylinderSolid(); + std::pair grid3DSolid(); std::pair icosphereSolid(); std::pair planeSolid(); std::pair uvSphereSolid(); @@ -257,6 +260,7 @@ int PrimitiveVisualizer::exec() { &PrimitiveVisualizer::coneWireframe, &PrimitiveVisualizer::cubeWireframe, &PrimitiveVisualizer::cylinderWireframe, + &PrimitiveVisualizer::grid3DWireframe, &PrimitiveVisualizer::line3D, &PrimitiveVisualizer::planeWireframe, &PrimitiveVisualizer::uvSphereWireframe}) @@ -337,6 +341,7 @@ int PrimitiveVisualizer::exec() { &PrimitiveVisualizer::coneSolid, &PrimitiveVisualizer::cubeSolid, &PrimitiveVisualizer::cylinderSolid, + &PrimitiveVisualizer::grid3DSolid, &PrimitiveVisualizer::icosphereSolid, &PrimitiveVisualizer::planeSolid, &PrimitiveVisualizer::uvSphereSolid}) @@ -421,6 +426,10 @@ std::pair PrimitiveVisualizer::cylinderWireframe return {Primitives::cylinderWireframe(1, 32, 1.0f), "cylinderwireframe.png"}; } +std::pair PrimitiveVisualizer::grid3DWireframe() { + return {Primitives::grid3DWireframe({5, 3}), "grid3dwireframe.png"}; +} + std::pair PrimitiveVisualizer::line3D() { auto line = Primitives::line3D(); MeshTools::transformPointsInPlace(Matrix4::translation(Vector3::xAxis(-1.0f))*Matrix4::scaling(Vector3::xScale(2.0f)), line.positions(0)); @@ -465,6 +474,10 @@ std::pair PrimitiveVisualizer::cylinderSolid() { return {Primitives::cylinderSolid(1, 12, 1.0f, Primitives::CylinderFlag::CapEnds), "cylindersolid.png"}; } +std::pair PrimitiveVisualizer::grid3DSolid() { + return {Primitives::grid3DSolid({5, 3}), "grid3dsolid.png"}; +} + std::pair PrimitiveVisualizer::icosphereSolid() { return {Primitives::icosphereSolid(1), "icospheresolid.png"}; } diff --git a/doc/primitives-grid3dsolid.png b/doc/primitives-grid3dsolid.png new file mode 100644 index 0000000000000000000000000000000000000000..510c58f58a423411b1e8762ca93bcf3dcab526c4 GIT binary patch literal 22276 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 Dtd`X^ literal 0 HcmV?d00001 diff --git a/src/Magnum/Primitives/CMakeLists.txt b/src/Magnum/Primitives/CMakeLists.txt index 7ab1d453f..bc72d40d6 100644 --- a/src/Magnum/Primitives/CMakeLists.txt +++ b/src/Magnum/Primitives/CMakeLists.txt @@ -31,6 +31,7 @@ set(MagnumPrimitives_SRCS Cone.cpp Cube.cpp Cylinder.cpp + Grid.cpp Icosphere.cpp Line.cpp Plane.cpp @@ -48,6 +49,7 @@ set(MagnumPrimitives_HEADERS Cone.h Cube.h Cylinder.h + Grid.h Icosphere.h Line.h Plane.h diff --git a/src/Magnum/Primitives/Grid.cpp b/src/Magnum/Primitives/Grid.cpp new file mode 100644 index 000000000..5b59f9af7 --- /dev/null +++ b/src/Magnum/Primitives/Grid.cpp @@ -0,0 +1,108 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + 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 "Grid.h" + +#include "Magnum/Mesh.h" +#include "Magnum/Math/Color.h" +#include "Magnum/Trade/MeshData3D.h" + +namespace Magnum { namespace Primitives { + +Trade::MeshData3D grid3DSolid(const Vector2i& subdivisions, const GridFlags flags) { + const Vector2i vertexCount = subdivisions + Vector2i{2}; + const Vector2i faceCount = subdivisions + Vector2i{1}; + + std::vector positions; + positions.reserve(vertexCount.product()); + for(Int y = 0; y != vertexCount.y(); ++y) + for(Int x = 0; x != vertexCount.x(); ++x) + positions.emplace_back((Vector2(x, y)/Vector2(faceCount))*2.0f - Vector2{1.0f}, 0.0f); + + std::vector indices; + indices.reserve(faceCount.product()*6); + for(Int y = 0; y != faceCount.y(); ++y) { + for(Int x = 0; x != faceCount.x(); ++x) { + /* 2--1 5 + | / /| + |/ / | + 0 3--4 */ + indices.insert(indices.end(), { + UnsignedInt(y*vertexCount.x() + x), + UnsignedInt((y + 1)*vertexCount.x() + x + 1), + UnsignedInt((y + 1)*vertexCount.x() + x + 0), + UnsignedInt(y*vertexCount.x() + x), + UnsignedInt(y*vertexCount.x() + x + 1), + UnsignedInt((y + 1)*vertexCount.x() + x + 1)}); + } + } + + std::vector> normals; + if(flags & GridFlag::GenerateNormals) + normals.emplace_back(positions.size(), Vector3::zAxis(1.0f)); + + std::vector> textureCoordinates; + if(flags & GridFlag::GenerateTextureCoords) { + textureCoordinates.emplace_back(); + textureCoordinates[0].reserve(positions.size()); + for(std::size_t i = 0; i != positions.size(); ++i) + textureCoordinates[0].emplace_back(positions[i].xy()*0.5f + Vector2{0.5f}); + } + + return Trade::MeshData3D{MeshPrimitive::Triangles, std::move(indices), {std::move(positions)}, std::move(normals), std::move(textureCoordinates), {}, nullptr}; +} + +Trade::MeshData3D grid3DWireframe(const Vector2i& subdivisions) { + const Vector2i vertexCount = subdivisions + Vector2i{2}; + const Vector2i faceCount = subdivisions + Vector2i{1}; + + std::vector positions; + positions.reserve(vertexCount.product()); + for(Int y = 0; y != vertexCount.y(); ++y) + for(Int x = 0; x != vertexCount.x(); ++x) + positions.emplace_back((Vector2(x, y)/Vector2(faceCount))*2.0f - Vector2{1.0f}, 0.0f); + + std::vector indices; + indices.reserve(vertexCount.y()*(vertexCount.x() - 1)*2 + + vertexCount.x()*(vertexCount.y() - 1)*2); + for(Int y = 0; y != vertexCount.y(); ++y) { + for(Int x = 0; x != vertexCount.x(); ++x) { + /* 3 7 + | | ... + 2 6 + 0--1 4--5 ... */ + if(x != vertexCount.x() - 1) indices.insert(indices.end(), { + UnsignedInt(y*vertexCount.x() + x), + UnsignedInt(y*vertexCount.x() + x + 1)}); + if(y != vertexCount.y() - 1) indices.insert(indices.end(), { + UnsignedInt(y*vertexCount.x() + x), + UnsignedInt((y + 1)*vertexCount.x() + x)}); + } + } + + return Trade::MeshData3D{MeshPrimitive::Lines, std::move(indices), {std::move(positions)}, {}, {}, {}, nullptr}; +} + +}} diff --git a/src/Magnum/Primitives/Grid.h b/src/Magnum/Primitives/Grid.h new file mode 100644 index 000000000..c049df981 --- /dev/null +++ b/src/Magnum/Primitives/Grid.h @@ -0,0 +1,101 @@ +#ifndef Magnum_Primitives_Grid_h +#define Magnum_Primitives_Grid_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + 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::Primitives::grid3DSolid(), @ref Magnum::Primitives::grid3DWireframe() + */ + +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Math/Math.h" +#include "Magnum/Primitives/visibility.h" +#include "Magnum/Trade/Trade.h" + +namespace Magnum { namespace Primitives { + +/** +@brief Grid flag + +@see @ref GridFlags, @ref grid3DSolid() +*/ +enum class GridFlag: UnsignedByte { + /** Generate texture coordinates with origin in bottom left corner. */ + GenerateTextureCoords = 1 << 0, + + /** + * Generate normals inn positive Z direction. Disable if you'd be + * generating your own normals anyway (for example based on a heightmap). + */ + GenerateNormals = 1 << 1 +}; + +/** +@brief Grid flags + +@see @ref grid3DSolid() +*/ +typedef Containers::EnumSet GridFlags; + +CORRADE_ENUMSET_OPERATORS(GridFlags) + +/** +@brief 3D solid grid + +2x2 grid. Indexed @ref MeshPrimitive::Triangles with optional normals and +texture coordinates. + +@image html primitives-grid3dsolid.png + +The @p subdivisions parameter describes how many times the plane gets cut in +each direction. Specifying @cpp {0, 0} @ce will make the result an (indexed) +equivalent to @ref planeSolid(); @cpp {5, 3} @ce will make the grid have 6 +cells horizontally and 4 vertically. In particular, this is different from the +`subdivisions` parameter in @ref icosphereSolid(). +@see @ref grid3DWireframe() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D grid3DSolid(const Vector2i& subdivisions, GridFlags flags = GridFlag::GenerateNormals); + +/** +@brief 3D wireframe grid + +2x2 grid. Indexed @ref MeshPrimitive::Lines. + +@image html primitives-grid3dwireframe.png + +The @p subdivisions parameter describes how many times the plane gets cut in +each direction. Specifying @cpp {0, 0} @ce will make the result an (indexed) +equivalent to @ref planeWireframe(); @cpp {5, 3} @ce will make the grid have 6 +cells horizontally and 4 vertically. In particular, this is different from the +`subdivisions` parameter in @ref icosphereSolid(). +@see @ref grid3DSolid() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D grid3DWireframe(const Vector2i& subdivisions); + +}} + +#endif diff --git a/src/Magnum/Primitives/Icosphere.h b/src/Magnum/Primitives/Icosphere.h index 8559446e2..ecd2d613e 100644 --- a/src/Magnum/Primitives/Icosphere.h +++ b/src/Magnum/Primitives/Icosphere.h @@ -47,6 +47,12 @@ normals. @image html primitives-icospheresolid.png +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(). @see @ref uvSphereSolid(), @ref uvSphereWireframe() */ MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D icosphereSolid(UnsignedInt subdivisions); diff --git a/src/Magnum/Primitives/Test/CMakeLists.txt b/src/Magnum/Primitives/Test/CMakeLists.txt index 28eb3a469..d0ff68730 100644 --- a/src/Magnum/Primitives/Test/CMakeLists.txt +++ b/src/Magnum/Primitives/Test/CMakeLists.txt @@ -30,6 +30,7 @@ corrade_add_test(PrimitivesCrosshairTest CrosshairTest.cpp LIBRARIES MagnumPrimi corrade_add_test(PrimitivesCubeTest CubeTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesConeTest ConeTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesCylinderTest CylinderTest.cpp LIBRARIES MagnumPrimitives) +corrade_add_test(PrimitivesGridTest GridTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesIcosphereTest IcosphereTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesLineTest LineTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesPlaneTest PlaneTest.cpp LIBRARIES MagnumPrimitives) diff --git a/src/Magnum/Primitives/Test/GridTest.cpp b/src/Magnum/Primitives/Test/GridTest.cpp new file mode 100644 index 000000000..851aeb317 --- /dev/null +++ b/src/Magnum/Primitives/Test/GridTest.cpp @@ -0,0 +1,377 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + 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 "Magnum/Math/Vector3.h" +#include "Magnum/Primitives/Grid.h" +#include "Magnum/Trade/MeshData3D.h" + +namespace Magnum { namespace Primitives { namespace Test { + +struct GridTest: TestSuite::Tester { + explicit GridTest(); + + void solid3DWithoutAnything(); + void solid3DWithNormalsAndTextureCoords(); + void wireframe3D(); +}; + +GridTest::GridTest() { + addTests({&GridTest::solid3DWithoutAnything, + &GridTest::solid3DWithNormalsAndTextureCoords, + &GridTest::wireframe3D}); +} + +void GridTest::solid3DWithoutAnything() { + Trade::MeshData3D grid = grid3DSolid({5, 3}, {}); + + CORRADE_COMPARE_AS(grid.positions(0), (std::vector{ + {-1.0f, -1.0f, 0.0f}, + {-0.666667f, -1.0f, 0.0f}, + {-0.333333f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.333333f, -1.0f, 0.0f}, + {0.666667f, -1.0f, 0.0f}, + {1.0f, -1.0f, 0.0f}, + + {-1.0f, -0.5f, 0.0f}, + {-0.666667f, -0.5f, 0.0f}, + {-0.333333f, -0.5f, 0.0f}, + {0.0f, -0.5f, 0.0f}, + {0.333333f, -0.5f, 0.0f}, + {0.666667f, -0.5f, 0.0f}, + {1.0f, -0.5f, 0.0f}, + + {-1.0f, 0.0f, 0.0f}, + {-0.666667f, 0.0f, 0.0f}, + {-0.333333f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f}, + {0.333333f, 0.0f, 0.0f}, + {0.666667f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + + {-1.0f, 0.5f, 0.0f}, + {-0.666667f, 0.5f, 0.0f}, + {-0.333333f, 0.5f, 0.0f}, + {0.0f, 0.5f, 0.0f}, + {0.333333f, 0.5f, 0.0f}, + {0.666667f, 0.5f, 0.0f}, + {1.0f, 0.5f, 0.0f}, + + {-1.0f, 1.0f, 0.0f}, + {-0.666667f, 1.0f, 0.0f}, + {-0.333333f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.333333f, 1.0f, 0.0f}, + {0.666667f, 1.0f, 0.0f}, + {1.0f, 1.0f, 0.0f} + }), TestSuite::Compare::Container); + + CORRADE_COMPARE(grid.normalArrayCount(), 0); + CORRADE_COMPARE(grid.textureCoords2DArrayCount(), 0); + + CORRADE_COMPARE_AS(grid.indices(), (std::vector{ + 0, 8, 7, 0, 1, 8, + 1, 9, 8, 1, 2, 9, + 2, 10, 9, 2, 3, 10, + 3, 11, 10, 3, 4, 11, + 4, 12, 11, 4, 5, 12, + 5, 13, 12, 5, 6, 13, + + 7, 15, 14, 7, 8, 15, + 8, 16, 15, 8, 9, 16, + 9, 17, 16, 9, 10, 17, + 10, 18, 17, 10, 11, 18, + 11, 19, 18, 11, 12, 19, + 12, 20, 19, 12, 13, 20, + + 14, 22, 21, 14, 15, 22, + 15, 23, 22, 15, 16, 23, + 16, 24, 23, 16, 17, 24, + 17, 25, 24, 17, 18, 25, + 18, 26, 25, 18, 19, 26, + 19, 27, 26, 19, 20, 27, + + 21, 29, 28, 21, 22, 29, + 22, 30, 29, 22, 23, 30, + 23, 31, 30, 23, 24, 31, + 24, 32, 31, 24, 25, 32, + 25, 33, 32, 25, 26, 33, + 26, 34, 33, 26, 27, 34 + }), TestSuite::Compare::Container); +} + +void GridTest::solid3DWithNormalsAndTextureCoords() { + Trade::MeshData3D grid = grid3DSolid({5, 3}, GridFlag::GenerateNormals|GridFlag::GenerateTextureCoords); + + CORRADE_COMPARE_AS(grid.positions(0), (std::vector{ + {-1.0f, -1.0f, 0.0f}, + {-0.666667f, -1.0f, 0.0f}, + {-0.333333f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.333333f, -1.0f, 0.0f}, + {0.666667f, -1.0f, 0.0f}, + {1.0f, -1.0f, 0.0f}, + + {-1.0f, -0.5f, 0.0f}, + {-0.666667f, -0.5f, 0.0f}, + {-0.333333f, -0.5f, 0.0f}, + {0.0f, -0.5f, 0.0f}, + {0.333333f, -0.5f, 0.0f}, + {0.666667f, -0.5f, 0.0f}, + {1.0f, -0.5f, 0.0f}, + + {-1.0f, 0.0f, 0.0f}, + {-0.666667f, 0.0f, 0.0f}, + {-0.333333f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f}, + {0.333333f, 0.0f, 0.0f}, + {0.666667f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + + {-1.0f, 0.5f, 0.0f}, + {-0.666667f, 0.5f, 0.0f}, + {-0.333333f, 0.5f, 0.0f}, + {0.0f, 0.5f, 0.0f}, + {0.333333f, 0.5f, 0.0f}, + {0.666667f, 0.5f, 0.0f}, + {1.0f, 0.5f, 0.0f}, + + {-1.0f, 1.0f, 0.0f}, + {-0.666667f, 1.0f, 0.0f}, + {-0.333333f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.333333f, 1.0f, 0.0f}, + {0.666667f, 1.0f, 0.0f}, + {1.0f, 1.0f, 0.0f} + }), TestSuite::Compare::Container); + + CORRADE_COMPARE_AS(grid.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}, + {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}, + {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}, + {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}, + }), TestSuite::Compare::Container); + + CORRADE_COMPARE_AS(grid.textureCoords2D(0), (std::vector{ + {0.0f, 0.0f}, + {0.166667f, 0.0f}, + {0.333333f, 0.0f}, + {0.5f, 0.0f}, + {0.666667f, 0.0f}, + {0.833333f, 0.0f}, + {1.0f, 0.0f}, + + {0.0f, 0.25f}, + {0.166667f, 0.25f}, + {0.333333f, 0.25f}, + {0.5f, 0.25f}, + {0.666667f, 0.25f}, + {0.833333f, 0.25f}, + {1.0f, 0.25f}, + + {0.0f, 0.5f}, + {0.166667f, 0.5f}, + {0.333333f, 0.5f}, + {0.5f, 0.5f}, + {0.666667f, 0.5f}, + {0.833333f, 0.5f}, + {1.0f, 0.5f}, + + {0.0f, 0.75f}, + {0.166667f, 0.75f}, + {0.333333f, 0.75f}, + {0.5f, 0.75f}, + {0.666667f, 0.75f}, + {0.833333f, 0.75f}, + {1.0f, 0.75f}, + + {0.0f, 1.0f}, + {0.166667f, 1.0f}, + {0.333333f, 1.0f}, + {0.5f, 1.0f}, + {0.666667f, 1.0f}, + {0.833333f, 1.0f}, + {1.0f, 1.0f} + }), TestSuite::Compare::Container); + + CORRADE_COMPARE_AS(grid.indices(), (std::vector{ + 0, 8, 7, 0, 1, 8, + 1, 9, 8, 1, 2, 9, + 2, 10, 9, 2, 3, 10, + 3, 11, 10, 3, 4, 11, + 4, 12, 11, 4, 5, 12, + 5, 13, 12, 5, 6, 13, + + 7, 15, 14, 7, 8, 15, + 8, 16, 15, 8, 9, 16, + 9, 17, 16, 9, 10, 17, + 10, 18, 17, 10, 11, 18, + 11, 19, 18, 11, 12, 19, + 12, 20, 19, 12, 13, 20, + + 14, 22, 21, 14, 15, 22, + 15, 23, 22, 15, 16, 23, + 16, 24, 23, 16, 17, 24, + 17, 25, 24, 17, 18, 25, + 18, 26, 25, 18, 19, 26, + 19, 27, 26, 19, 20, 27, + + 21, 29, 28, 21, 22, 29, + 22, 30, 29, 22, 23, 30, + 23, 31, 30, 23, 24, 31, + 24, 32, 31, 24, 25, 32, + 25, 33, 32, 25, 26, 33, + 26, 34, 33, 26, 27, 34 + }), TestSuite::Compare::Container); +} + +void GridTest::wireframe3D() { + Trade::MeshData3D grid = grid3DWireframe({5, 3}); + + CORRADE_COMPARE_AS(grid.positions(0), (std::vector{ + {-1.0f, -1.0f, 0.0f}, + {-0.666667f, -1.0f, 0.0f}, + {-0.333333f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.333333f, -1.0f, 0.0f}, + {0.666667f, -1.0f, 0.0f}, + {1.0f, -1.0f, 0.0f}, + + {-1.0f, -0.5f, 0.0f}, + {-0.666667f, -0.5f, 0.0f}, + {-0.333333f, -0.5f, 0.0f}, + {0.0f, -0.5f, 0.0f}, + {0.333333f, -0.5f, 0.0f}, + {0.666667f, -0.5f, 0.0f}, + {1.0f, -0.5f, 0.0f}, + + {-1.0f, 0.0f, 0.0f}, + {-0.666667f, 0.0f, 0.0f}, + {-0.333333f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f}, + {0.333333f, 0.0f, 0.0f}, + {0.666667f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + + {-1.0f, 0.5f, 0.0f}, + {-0.666667f, 0.5f, 0.0f}, + {-0.333333f, 0.5f, 0.0f}, + {0.0f, 0.5f, 0.0f}, + {0.333333f, 0.5f, 0.0f}, + {0.666667f, 0.5f, 0.0f}, + {1.0f, 0.5f, 0.0f}, + + {-1.0f, 1.0f, 0.0f}, + {-0.666667f, 1.0f, 0.0f}, + {-0.333333f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.333333f, 1.0f, 0.0f}, + {0.666667f, 1.0f, 0.0f}, + {1.0f, 1.0f, 0.0f} + }), TestSuite::Compare::Container); + + CORRADE_COMPARE_AS(grid.indices(), (std::vector{ + 0, 1, 0, 7, + 1, 2, 1, 8, + 2, 3, 2, 9, + 3, 4, 3, 10, + 4, 5, 4, 11, + 5, 6, 5, 12, + 6, 13, + + 7, 8, 7, 14, + 8, 9, 8, 15, + 9, 10, 9, 16, + 10, 11, 10, 17, + 11, 12, 11, 18, + 12, 13, 12, 19, + 13, 20, + + 14, 15, 14, 21, + 15, 16, 15, 22, + 16, 17, 16, 23, + 17, 18, 17, 24, + 18, 19, 18, 25, + 19, 20, 19, 26, + 20, 27, + + 21, 22, 21, 28, + 22, 23, 22, 29, + 23, 24, 23, 30, + 24, 25, 24, 31, + 25, 26, 25, 32, + 26, 27, 26, 33, + 27, 34, + + 28, 29, + 29, 30, + 30, 31, + 31, 32, + 32, 33, + 33, 34 + }), TestSuite::Compare::Container); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Primitives::Test::GridTest)