diff --git a/doc/changelog.dox b/doc/changelog.dox index 20dcdaf0e..515adb460 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -160,6 +160,10 @@ See also: @subsubsection changelog-latest-new-primitives Primitives library +- New @ref Primitives::gradient2D(), @ref Primitives::gradient2DHorizontal(), + @ref Primitives::gradient2DVertical(), @ref Primitives::gradient3D(), + @ref Primitives::gradient3DHorizontal() and + @ref Primitives::gradient3DVertical() primitives - New @ref Primitives::line2D(const Vector2&, const Vector2&) and @ref Primitives::line3D(const Vector3&, const Vector3&) overloads for easier creation of arbitrary lines, as transforming the line identities is diff --git a/doc/generated/primitives.cpp b/doc/generated/primitives.cpp index 817ba07a8..ce9600d6e 100644 --- a/doc/generated/primitives.cpp +++ b/doc/generated/primitives.cpp @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -117,6 +118,14 @@ struct PrimitiveVisualizer: Platform::WindowlessApplication { std::pair icosphereSolid(); std::pair planeSolid(); std::pair uvSphereSolid(); + + std::pair gradient2D(); + std::pair gradient2DHorizontal(); + std::pair gradient2DVertical(); + + std::pair gradient3D(); + std::pair gradient3DHorizontal(); + std::pair gradient3DVertical(); }; namespace { @@ -346,6 +355,52 @@ int PrimitiveVisualizer::exec() { } } + { + Shaders::VertexColor2D shader; + shader.setTransformationProjectionMatrix(Projection2D*Transformation2D); + + for(auto fun: {&PrimitiveVisualizer::gradient2D, + &PrimitiveVisualizer::gradient2DHorizontal, + &PrimitiveVisualizer::gradient2DVertical}) { + multisampleFramebuffer.clear(GL::FramebufferClear::Color|GL::FramebufferClear::Depth); + + std::string filename; + Containers::Optional data; + std::tie(data, filename) = (this->*fun)(); + + MeshTools::compile(*data) + .draw(shader) + .draw(wireframe2D); + + GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); + Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); + converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); + } + } + + { + Shaders::VertexColor3D shader; + shader.setTransformationProjectionMatrix(Projection3D*Transformation3D); + + for(auto fun: {&PrimitiveVisualizer::gradient3D, + &PrimitiveVisualizer::gradient3DHorizontal, + &PrimitiveVisualizer::gradient3DVertical}) { + multisampleFramebuffer.clear(GL::FramebufferClear::Color|GL::FramebufferClear::Depth); + + std::string filename; + Containers::Optional data; + std::tie(data, filename) = (this->*fun)(); + + MeshTools::compile(*data) + .draw(shader) + .draw(wireframe3D); + + GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); + Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); + converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); + } + } + return 0; } @@ -353,10 +408,42 @@ std::pair PrimitiveVisualizer::axis2D() { return {Primitives::axis2D(), "axis2d.png"}; } +std::pair PrimitiveVisualizer::gradient2D() { + return {Primitives::gradient2D({1.0f, -2.0f}, 0x2f83cc_srgbf, {-1.0f, 2.0f}, 0x3bd267_srgbf), "gradient2d.png"}; +} + +namespace { + /* End colors for axis-aligned gradients are 20%/80% blends of the above to + match the range */ + const Color3 Gradient20Percent = Math::lerp(0x2f83cc_srgbf, 0x3bd267_srgbf, 0.2f); + const Color3 Gradient80Percent = Math::lerp(0x2f83cc_srgbf, 0x3bd267_srgbf, 0.8f); +} + +std::pair PrimitiveVisualizer::gradient2DHorizontal() { + return {Primitives::gradient2DHorizontal(Gradient20Percent, Gradient80Percent), "gradient2dhorizontal.png"}; +} + +std::pair PrimitiveVisualizer::gradient2DVertical() { + /* End colors are 20%/80% blends of the above to match the range */ + return {Primitives::gradient2DVertical(Gradient20Percent, Gradient80Percent), "gradient2dvertical.png"}; +} + std::pair PrimitiveVisualizer::axis3D() { return {Primitives::axis3D(), "axis3d.png"}; } +std::pair PrimitiveVisualizer::gradient3D() { + return {Primitives::gradient3D({1.0f, -2.0f, -1.5f}, 0x2f83cc_srgbf, {-1.0f, 2.0f, -1.5f}, 0x3bd267_srgbf), "gradient3d.png"}; +} + +std::pair PrimitiveVisualizer::gradient3DHorizontal() { + return {Primitives::gradient3DHorizontal(Gradient20Percent, Gradient80Percent), "gradient3dhorizontal.png"}; +} + +std::pair PrimitiveVisualizer::gradient3DVertical() { + return {Primitives::gradient3DVertical(Gradient20Percent, Gradient80Percent), "gradient3dvertical.png"}; +} + std::pair PrimitiveVisualizer::capsule2DWireframe() { auto capsule = Primitives::capsule2DWireframe(8, 1, 0.75f); MeshTools::transformPointsInPlace(Matrix3::scaling(Vector2{0.75f}), capsule.positions(0)); diff --git a/doc/primitives-gradient2d.png b/doc/primitives-gradient2d.png new file mode 100644 index 000000000..667881977 Binary files /dev/null and b/doc/primitives-gradient2d.png differ diff --git a/doc/primitives-gradient2dhorizontal.png b/doc/primitives-gradient2dhorizontal.png new file mode 100644 index 000000000..8a3c73bb2 Binary files /dev/null and b/doc/primitives-gradient2dhorizontal.png differ diff --git a/doc/primitives-gradient2dvertical.png b/doc/primitives-gradient2dvertical.png new file mode 100644 index 000000000..66118c9c7 Binary files /dev/null and b/doc/primitives-gradient2dvertical.png differ diff --git a/doc/primitives-gradient3d.png b/doc/primitives-gradient3d.png new file mode 100644 index 000000000..309b38b9c Binary files /dev/null and b/doc/primitives-gradient3d.png differ diff --git a/doc/primitives-gradient3dhorizontal.png b/doc/primitives-gradient3dhorizontal.png new file mode 100644 index 000000000..c4c4029aa Binary files /dev/null and b/doc/primitives-gradient3dhorizontal.png differ diff --git a/doc/primitives-gradient3dvertical.png b/doc/primitives-gradient3dvertical.png new file mode 100644 index 000000000..1f84fc662 Binary files /dev/null and b/doc/primitives-gradient3dvertical.png differ diff --git a/doc/snippets/MagnumPrimitives.cpp b/doc/snippets/MagnumPrimitives.cpp index 4ac9da13e..b0091ddf9 100644 --- a/doc/snippets/MagnumPrimitives.cpp +++ b/doc/snippets/MagnumPrimitives.cpp @@ -23,7 +23,8 @@ DEALINGS IN THE SOFTWARE. */ -#include "Magnum/Math/Vector3.h" +#include "Magnum/Math/Color.h" +#include "Magnum/Primitives/Gradient.h" #include "Magnum/Primitives/Line.h" #include "Magnum/Trade/MeshData2D.h" #include "Magnum/Trade/MeshData3D.h" @@ -31,6 +32,25 @@ using namespace Magnum; int main() { +{ +Color4 colorA, colorB; +/* [gradient2DHorizontal] */ +Primitives::gradient2D({-1.0f, 0.0f}, colorA, {1.0f, 0.0f}, colorB); +/* [gradient2DHorizontal] */ + +/* [gradient2DVertical] */ +Primitives::gradient2D({0.0f, -1.0f}, colorA, {0.0f, 1.0f}, colorB); +/* [gradient2DVertical] */ + +/* [gradient3DHorizontal] */ +Primitives::gradient3D({-1.0f, 0.0f, 0.0f}, colorA, {1.0f, 0.0f, 0.0f}, colorB); +/* [gradient3DHorizontal] */ + +/* [gradient3DVertical] */ +Primitives::gradient3D({0.0f, -1.0f, 0.0f}, colorA, {0.0f, 1.0f, 0.0f}, colorB); +/* [gradient3DVertical] */ +} + { /* [line2D-identity] */ Primitives::line2D({0.0f, 0.0f}, {1.0f, 0.0f}); diff --git a/src/Magnum/Primitives/CMakeLists.txt b/src/Magnum/Primitives/CMakeLists.txt index 7fead0fcb..98e2ab79b 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 + Gradient.cpp Grid.cpp Icosphere.cpp Line.cpp @@ -49,6 +50,7 @@ set(MagnumPrimitives_HEADERS Cone.h Cube.h Cylinder.h + Gradient.h Grid.h Icosphere.h Line.h diff --git a/src/Magnum/Primitives/Gradient.cpp b/src/Magnum/Primitives/Gradient.cpp new file mode 100644 index 000000000..ab427713b --- /dev/null +++ b/src/Magnum/Primitives/Gradient.cpp @@ -0,0 +1,99 @@ +/* + 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 "Gradient.h" + +#include "Magnum/Mesh.h" +#include "Magnum/Math/Color.h" +#include "Magnum/Math/Intersection.h" +#include "Magnum/Trade/MeshData2D.h" +#include "Magnum/Trade/MeshData3D.h" + +namespace Magnum { namespace Primitives { + +Trade::MeshData2D gradient2D(const Vector2& a, const Color4& colorA, const Vector2& b, const Color4& colorB) { + std::vector positions{Vector2{ 1.0f, -1.0f}, + Vector2{ 1.0f, 1.0f}, + Vector2{-1.0f, -1.0f}, + Vector2{-1.0f, 1.0f}}; + std::vector colors{4}; + + /* For every corner, take a line perpendicular to the gradient direction + and passing through the corner. The calculated intersection position + with the gradient line segment is the blend factor for the two colors + for given corner. */ + const Vector2 direction = b - a; + const Vector2 perpendicular = direction.perpendicular(); + for(std::size_t i = 0; i != 4; ++i) { + const Float t = Math::Intersection::lineSegmentLine(a, direction, positions[i], perpendicular); + colors[i] = Math::lerp(colorA, colorB, t); + } + + return Trade::MeshData2D{MeshPrimitive::TriangleStrip, {}, {std::move(positions)}, {}, {std::move(colors)}, nullptr}; +} + +Trade::MeshData2D gradient2DHorizontal(const Color4& colorA, const Color4& colorB) { + return Primitives::gradient2D({-1.0f, 0.0f}, colorA, {1.0f, 0.0f}, colorB); +} + +Trade::MeshData2D gradient2DVertical(const Color4& colorA, const Color4& colorB) { + return Primitives::gradient2D({0.0f, -1.0f}, colorA, {0.0f, 1.0f}, colorB); +} + +Trade::MeshData3D gradient3D(const Vector3& a, const Color4& colorA, const Vector3& b, const Color4& colorB) { + std::vector positions{Vector3{ 1.0f, -1.0f, 0.0f}, + Vector3{ 1.0f, 1.0f, 0.0f}, + Vector3{-1.0f, -1.0f, 0.0f}, + Vector3{-1.0f, 1.0f, 0.0f}}; + std::vector colors{4}; + + /* For every corner, take a plane perpendicular to the gradient direction + and passing through the corner. The calculated intersection position + with the gradient line segment is the blend factor for the two colors + for given corner. */ + const Vector3 direction = b - a; + for(std::size_t i = 0; i != 4; ++i) { + const Vector4 plane = Math::planeEquation(direction, positions[i]); + const Float t = Math::Intersection::planeLine(plane, a, direction); + colors[i] = Math::lerp(colorA, colorB, t); + } + + return Trade::MeshData3D{MeshPrimitive::TriangleStrip, {}, {std::move(positions)}, {{ + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f} + }}, {}, {std::move(colors)}, nullptr}; +} + +Trade::MeshData3D gradient3DHorizontal(const Color4& colorA, const Color4& colorB) { + return Primitives::gradient3D({-1.0f, 0.0f, 0.0f}, colorA, {1.0f, 0.0f, 0.0f}, colorB); +} + +Trade::MeshData3D gradient3DVertical(const Color4& colorA, const Color4& colorB) { + return Primitives::gradient3D({0.0f, -1.0f, 0.0f}, colorA, {0.0f, 1.0f, 0.0f}, colorB); +} + +}} diff --git a/src/Magnum/Primitives/Gradient.h b/src/Magnum/Primitives/Gradient.h new file mode 100644 index 000000000..2c288ffc9 --- /dev/null +++ b/src/Magnum/Primitives/Gradient.h @@ -0,0 +1,121 @@ +#ifndef Magnum_Primitives_Gradient_h +#define Magnum_Primitives_Gradient_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::gradient2D(), @ref Magnum::Primitives::gradient2DHorizontal(), @ref Magnum::Primitives::gradient2DVertical(), @ref Magnum::Primitives::gradient3D(), @ref Magnum::Primitives::gradient3DHorizontal(), @ref Magnum::Primitives::gradient3DVertical() + */ + +#include "Magnum/Magnum.h" +#include "Magnum/Primitives/visibility.h" +#include "Magnum/Trade/Trade.h" + +namespace Magnum { namespace Primitives { + +/** +@brief 2D square with a gradient + +2x2 square with vertex colors. Non-indexed @ref MeshPrimitive::TriangleStrip. +Vertex colors correspond to the gradient defined by the endpoints @p a and +@p b, linearly interpolated from @p colorA to @p colorB. + +@image html primitives-gradient2d.png width=256px + +@see @ref gradient2DHorizontal(), @ref gradient2DVertical(), @ref gradient3D(), + @ref squareSolid() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData2D gradient2D(const Vector2& a, const Color4& colorA, const Vector2& b, const Color4& colorB); + +/** +@brief 2D square with a horizontal gradient + +Equivalent to calling @ref gradient2D() like this: + +@snippet MagnumPrimitives.cpp gradient2DHorizontal + +@image html primitives-gradient2dhorizontal.png width=256px + +@see @ref gradient2DVertical(), @ref gradient3DHorizontal(), @ref squareSolid() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData2D gradient2DHorizontal(const Color4& colorLeft, const Color4& color); + +/** +@brief 2D square with a vertical gradient + +Equivalent to calling @ref gradient2D() like this: + +@snippet MagnumPrimitives.cpp gradient2DVertical + +@image html primitives-gradient2dvertical.png width=256px + +@see @ref gradient2DHorizontal(), @ref gradient3DVertical(), @ref squareSolid() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData2D gradient2DVertical(const Color4& colorBottom, const Color4& colorTop); + +/** +@brief 3D plane with a gradient + +2x2 plane with vertex colors. Non-indexed @ref MeshPrimitive::TriangleStrip on +the XY plane with normals in positive Z direction. Vertex colors correspond to +the gradient defined by the endpoints @p a and @p b, linearly interpolated from +@p colorA to @p colorB. + +@image html primitives-gradient3d.png width=256px + +@see @ref gradient3DHorizontal(), @ref gradient3DVertical(), @ref gradient2D(), + @ref planeSolid() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D gradient3D(const Vector3& a, const Color4& colorA, const Vector3& b, const Color4& colorB); + +/** +@brief 3D plane with a horizontal gradient + +Equivalent to calling @ref gradient3D() like this: + +@snippet MagnumPrimitives.cpp gradient3DHorizontal + +@image html primitives-gradient3dhorizontal.png width=256px + +@see @ref gradient3DVertical(), @ref gradient2DHorizontal(), @ref planeSolid() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D gradient3DHorizontal(const Color4& colorLeft, const Color4& color); + +/** +@brief 3D plane with a vertical gradient + +Equivalent to calling @ref gradient3D() like this: + +@snippet MagnumPrimitives.cpp gradient3DVertical + +@image html primitives-gradient3dvertical.png width=256px + +@see @ref gradient3DHorizontal(), @ref gradient2DVertical(), @ref planeSolid() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D gradient3DVertical(const Color4& colorBottom, const Color4& colorTop); + +}} + +#endif diff --git a/src/Magnum/Primitives/Plane.h b/src/Magnum/Primitives/Plane.h index a2631037f..7f3ecb35c 100644 --- a/src/Magnum/Primitives/Plane.h +++ b/src/Magnum/Primitives/Plane.h @@ -58,7 +58,7 @@ normals in positive Z direction. @image html primitives-planesolid.png width=256px -@see @ref planeWireframe(), @ref squareSolid() +@see @ref planeWireframe(), @ref squareSolid(), @ref gradient3D() */ MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D planeSolid(PlaneTextureCoords textureCoords = PlaneTextureCoords::DontGenerate); diff --git a/src/Magnum/Primitives/Square.h b/src/Magnum/Primitives/Square.h index 4716f6cb4..b56dbf05a 100644 --- a/src/Magnum/Primitives/Square.h +++ b/src/Magnum/Primitives/Square.h @@ -57,7 +57,7 @@ enum class SquareTextureCoords: UnsignedByte { @image html primitives-squaresolid.png width=256px -@see @ref squareWireframe(), @ref planeSolid() +@see @ref squareWireframe(), @ref planeSolid(), @ref gradient2D() */ MAGNUM_PRIMITIVES_EXPORT Trade::MeshData2D squareSolid(SquareTextureCoords textureCoords = SquareTextureCoords::DontGenerate); diff --git a/src/Magnum/Primitives/Test/CMakeLists.txt b/src/Magnum/Primitives/Test/CMakeLists.txt index ef3493e77..ed4ac6cd6 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(PrimitivesGradientTest GradientTest.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) @@ -45,6 +46,7 @@ set_target_properties( PrimitivesCubeTest PrimitivesConeTest PrimitivesCylinderTest + PrimitivesGradientTest PrimitivesGridTest PrimitivesIcosphereTest PrimitivesLineTest diff --git a/src/Magnum/Primitives/Test/GradientTest.cpp b/src/Magnum/Primitives/Test/GradientTest.cpp new file mode 100644 index 000000000..c0965a0fc --- /dev/null +++ b/src/Magnum/Primitives/Test/GradientTest.cpp @@ -0,0 +1,167 @@ +/* + 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/Mesh.h" +#include "Magnum/Math/Color.h" +#include "Magnum/Primitives/Gradient.h" +#include "Magnum/Trade/MeshData2D.h" +#include "Magnum/Trade/MeshData3D.h" +#include "Magnum/Primitives/Square.h" +#include "Magnum/Primitives/Plane.h" + +namespace Magnum { namespace Primitives { namespace Test { + +struct GradientTest: TestSuite::Tester { + explicit GradientTest(); + + void gradient2D(); + void gradient2DHorizontal(); + void gradient2DVertical(); + + void gradient3D(); + void gradient3DHorizontal(); + void gradient3DVertical(); +}; + +GradientTest::GradientTest() { + addTests({&GradientTest::gradient2D, + &GradientTest::gradient2DHorizontal, + &GradientTest::gradient2DVertical, + + &GradientTest::gradient3D, + &GradientTest::gradient3DHorizontal, + &GradientTest::gradient3DVertical}); +} + +using namespace Magnum::Math::Literals; + +void GradientTest::gradient2D() { + /* The corners sould have 0.2, 0.4, 0.6, 0.8 blends */ + Trade::MeshData2D gradient = Primitives::gradient2D( + {-1.0f, 2.0f}, {0.2f, 0.6f, 1.0f}, + {1.0f, -2.0f}, {0.4f, 1.0f, 0.0f}); + + /* Positions should be the same as for a square */ + Trade::MeshData2D square = Primitives::squareSolid(); + CORRADE_COMPARE(gradient.primitive(), square.primitive()); + CORRADE_COMPARE_AS(gradient.positions(0), square.positions(0), TestSuite::Compare::Container); + CORRADE_COMPARE_AS(gradient.positions(0), (std::vector{ + { 1.0f, -1.0f}, /* Bottom right */ + { 1.0f, 1.0f}, /* Top right */ + {-1.0f, -1.0f}, /* Bottom left */ + {-1.0f, 1.0f} /* Top left */ + }), TestSuite::Compare::Container); + + CORRADE_COMPARE(gradient.colorArrayCount(), 1); + CORRADE_COMPARE_AS(gradient.colors(0), (std::vector{ + {0.36f, 0.92f, 0.2f}, /* 80% */ + {0.28f, 0.76f, 0.6f}, /* 40% */ + {0.32f, 0.84f, 0.4f}, /* 60% */ + {0.24f, 0.68f, 0.8f} /* 20% */ + }), TestSuite::Compare::Container); +} + +void GradientTest::gradient2DHorizontal() { + Trade::MeshData2D gradient = Primitives::gradient2DHorizontal(0xfabcde_srgbf, 0xdeab09_srgbf); + + CORRADE_COMPARE(gradient.colorArrayCount(), 1); + CORRADE_COMPARE_AS(gradient.colors(0), (std::vector{ + 0xdeab09_srgbf, + 0xdeab09_srgbf, + 0xfabcde_srgbf, + 0xfabcde_srgbf + }), TestSuite::Compare::Container); +} + +void GradientTest::gradient2DVertical() { + Trade::MeshData2D gradient = Primitives::gradient2DVertical(0xfabcde_srgbf, 0xdeab09_srgbf); + + CORRADE_COMPARE(gradient.colorArrayCount(), 1); + CORRADE_COMPARE_AS(gradient.colors(0), (std::vector{ + 0xfabcde_srgbf, + 0xdeab09_srgbf, + 0xfabcde_srgbf, + 0xdeab09_srgbf + }), TestSuite::Compare::Container); +} + +void GradientTest::gradient3D() { + /* The corners sould have 0.2, 0.4, 0.6, 0.8 blends */ + Trade::MeshData3D gradient = Primitives::gradient3D( + {-1.0f, 2.0f, -1.5f}, {0.2f, 0.6f, 1.0f}, + {1.0f, -2.0f, -1.5f}, {0.4f, 1.0f, 0.0f}); + + /* Positions should be the same as for a plane */ + Trade::MeshData3D plane = Primitives::planeSolid(); + CORRADE_COMPARE(gradient.primitive(), plane.primitive()); + CORRADE_COMPARE_AS(gradient.positions(0), plane.positions(0), TestSuite::Compare::Container); + CORRADE_COMPARE_AS(gradient.positions(0), (std::vector{ + { 1.0f, -1.0f, 0.0f}, /* Bottom right */ + { 1.0f, 1.0f, 0.0f}, /* Top right */ + {-1.0f, -1.0f, 0.0f}, /* Bottom left */ + {-1.0f, 1.0f, 0.0f} /* Top left */ + }), TestSuite::Compare::Container); + + CORRADE_COMPARE(gradient.normalArrayCount(), 1); + + CORRADE_COMPARE(gradient.colorArrayCount(), 1); + CORRADE_COMPARE_AS(gradient.colors(0), (std::vector{ + {0.36f, 0.92f, 0.2f}, /* 80% */ + {0.28f, 0.76f, 0.6f}, /* 40% */ + {0.32f, 0.84f, 0.4f}, /* 60% */ + {0.24f, 0.68f, 0.8f} /* 20% */ + }), TestSuite::Compare::Container); +} + +void GradientTest::gradient3DHorizontal() { + Trade::MeshData3D gradient = Primitives::gradient3DHorizontal(0xfabcde_srgbf, 0xdeab09_srgbf); + + CORRADE_COMPARE(gradient.colorArrayCount(), 1); + CORRADE_COMPARE_AS(gradient.colors(0), (std::vector{ + 0xdeab09_srgbf, + 0xdeab09_srgbf, + 0xfabcde_srgbf, + 0xfabcde_srgbf + }), TestSuite::Compare::Container); +} + +void GradientTest::gradient3DVertical() { + Trade::MeshData3D gradient = Primitives::gradient3DVertical(0xfabcde_srgbf, 0xdeab09_srgbf); + + CORRADE_COMPARE(gradient.colorArrayCount(), 1); + CORRADE_COMPARE_AS(gradient.colors(0), (std::vector{ + 0xfabcde_srgbf, + 0xdeab09_srgbf, + 0xfabcde_srgbf, + 0xdeab09_srgbf + }), TestSuite::Compare::Container); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Primitives::Test::GradientTest)