diff --git a/src/Math/CMakeLists.txt b/src/Math/CMakeLists.txt index a92da34c4..ef962ab43 100644 --- a/src/Math/CMakeLists.txt +++ b/src/Math/CMakeLists.txt @@ -10,6 +10,7 @@ set(MagnumMath_HEADERS Point2D.h Point3D.h RectangularMatrix.h + Swizzle.h Vector.h Vector2.h Vector3.h diff --git a/src/Math/Swizzle.h b/src/Math/Swizzle.h new file mode 100644 index 000000000..482236d29 --- /dev/null +++ b/src/Math/Swizzle.h @@ -0,0 +1,74 @@ +#ifndef Magnum_Math_Swizzle_h +#define Magnum_Math_Swizzle_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Function Magnum::Math::swizzle() + */ + +#include "Vector.h" + +namespace Magnum { namespace Math { + +#ifndef DOXYGEN_GENERATING_OUTPUT +namespace Implementation { + template struct ComponentAtPosition { + static_assert(size > position, "Swizzle parameter out of range of base vector"); + + template inline constexpr static T value(const Math::Vector& vector) { return vector[position]; } + }; + + template struct Component {}; + template struct Component: public ComponentAtPosition {}; + template struct Component: public ComponentAtPosition {}; + template struct Component: public ComponentAtPosition {}; + template struct Component: public ComponentAtPosition {}; + template struct Component { + template inline constexpr static T value(const Math::Vector&) { return T(0); } + }; + template struct Component { + template inline constexpr static T value(const Math::Vector&) { return T(1); } + }; +} +#endif + +/** +@brief Swizzle Vector components + +Creates new vector from given components. Example: +@code +Vector4 original(-1, 2, 3, 4); + +auto vec = swizzle<'w', '1', '0', 'x', 'y', 'z'>(original); +// vec == { 4, 1, 0, -1, 2, 3 } +@endcode +You can use letters `x`, `y`, `z`, `w` for addressing components or letters +`0` and `1` for zero and one. Count of elements is unlimited, but must be at +least one. + +See also Magnum::swizzle() which has some added convenience features not +present in this lightweight implementation for Math namespace. + +@see @ref matrix-vector-component-access, Vector4::xyz(), + Vector4::xy(), Vector3::xy() +*/ +template inline constexpr Vector swizzle(const Vector& vector) { + return {Implementation::Component::value(vector)...}; +} + +}} + +#endif diff --git a/src/Math/Test/CMakeLists.txt b/src/Math/Test/CMakeLists.txt index ad6385d3f..2d0739185 100644 --- a/src/Math/Test/CMakeLists.txt +++ b/src/Math/Test/CMakeLists.txt @@ -16,4 +16,6 @@ corrade_add_test(MathMatrixTest MatrixTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathMatrix3Test Matrix3Test.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathMatrix4Test Matrix4Test.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(MathSwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib) + set_target_properties(MathVectorTest MathMatrix4Test PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) diff --git a/src/Math/Test/SwizzleTest.cpp b/src/Math/Test/SwizzleTest.cpp new file mode 100644 index 000000000..78fc7a1dd --- /dev/null +++ b/src/Math/Test/SwizzleTest.cpp @@ -0,0 +1,49 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "SwizzleTest.h" + +#include "Math/Swizzle.h" + +CORRADE_TEST_MAIN(Magnum::Math::Test::SwizzleTest) + +namespace Magnum { namespace Math { namespace Test { + +typedef Vector<4, std::int32_t> Vector4i; + +SwizzleTest::SwizzleTest() { + addTests(&SwizzleTest::components, + &SwizzleTest::constants, + &SwizzleTest::sizes); +} + +void SwizzleTest::components() { + CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y'>(Vector4i(2, 4, 5, 7))), Vector4i(5, 2, 7, 4)); +} + +void SwizzleTest::constants() { + CORRADE_COMPARE((swizzle<'1', 'w', '0', 'y'>(Vector4i(2, 4, 5, 7))), Vector4i(1, 7, 0, 4)); +} + +void SwizzleTest::sizes() { + CORRADE_COMPARE((swizzle<'y', 'x', 'x'>(Math::Vector<2, std::int32_t>(1, 2))), + (Math::Vector<3, std::int32_t>(2, 1, 1))); + CORRADE_COMPARE(swizzle<'z'>(Vector4i(1, 2, 3, 4)), + (Math::Vector<1, std::int32_t>(3))); + CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y', 'z', 'y', 'x'>(Vector4i(1, 2, 3, 4))), + (Math::Vector<7, std::int32_t>(3, 1, 4, 2, 3, 2, 1))); +} + +}}} diff --git a/src/Math/Test/SwizzleTest.h b/src/Math/Test/SwizzleTest.h new file mode 100644 index 000000000..a2d64fb2a --- /dev/null +++ b/src/Math/Test/SwizzleTest.h @@ -0,0 +1,33 @@ +#ifndef Magnum_Math_Test_SwizzleTest_h +#define Magnum_Math_Test_SwizzleTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Math { namespace Test { + +class SwizzleTest: public Corrade::TestSuite::Tester { + public: + SwizzleTest(); + + void components(); + void constants(); + void sizes(); +}; + +}}} + +#endif diff --git a/src/Swizzle.h b/src/Swizzle.h index af2ff2186..f3befdf78 100644 --- a/src/Swizzle.h +++ b/src/Swizzle.h @@ -15,38 +15,24 @@ GNU Lesser General Public License version 3 for more details. */ -/** @file +/** @file /Swizzle.h * @brief Function Magnum::swizzle() */ +#include "Math/Swizzle.h" #include "Color.h" namespace Magnum { #ifndef DOXYGEN_GENERATING_OUTPUT -namespace Implementation { - template struct ComponentAtPosition { - static_assert(size > position, "Swizzle parameter out of range of base vector"); - - template inline constexpr static T value(const Math::Vector& vector) { return vector[position]; } - }; - - template struct Component {}; - template struct Component: public ComponentAtPosition {}; - template struct Component: public ComponentAtPosition {}; - template struct Component: public ComponentAtPosition {}; - template struct Component: public ComponentAtPosition {}; +namespace Math { namespace Implementation { template struct Component: public ComponentAtPosition {}; template struct Component: public ComponentAtPosition {}; template struct Component: public ComponentAtPosition {}; template struct Component: public ComponentAtPosition {}; - template struct Component { - template inline constexpr static T value(const Math::Vector&) { return T(0); } - }; - template struct Component { - template inline constexpr static T value(const Math::Vector&) { return T(1); } - }; +}} +namespace Implementation { template struct TypeForSize { typedef Math::Vector Type; }; @@ -76,11 +62,11 @@ unlimited, but must be at least one. If the resulting vector is two, three or four-component, corresponding Math::Vector2, Math::Vector3, Math::Vector4, Color3 or Color4 specialization is returned. -@see @ref matrix-vector-component-access, Vector4::xyz(), Color4::rgb(), - Vector4::xy(), Vector3::xy() +@see @ref matrix-vector-component-access, Math::swizzle(), Vector4::xyz(), + Color4::rgb(), Vector4::xy(), Vector3::xy() */ template inline constexpr typename Implementation::TypeForSize::Type swizzle(const T& vector) { - return {Implementation::Component::value(vector)...}; + return {Math::Implementation::Component::value(vector)...}; } } diff --git a/src/Test/SwizzleTest.cpp b/src/Test/SwizzleTest.cpp index 627d302c2..b07c4da34 100644 --- a/src/Test/SwizzleTest.cpp +++ b/src/Test/SwizzleTest.cpp @@ -22,30 +22,15 @@ CORRADE_TEST_MAIN(Magnum::Test::SwizzleTest) namespace Magnum { namespace Test { SwizzleTest::SwizzleTest() { - addTests(&SwizzleTest::xyzw, - &SwizzleTest::rgba, - &SwizzleTest::constants, - &SwizzleTest::fromSmall, + addTests(&SwizzleTest::rgba, &SwizzleTest::type, &SwizzleTest::defaultType); } -void SwizzleTest::xyzw() { - CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y'>(Vector4i(2, 4, 5, 7))), Vector4i(5, 2, 7, 4)); -} - void SwizzleTest::rgba() { CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g'>(Vector4i(2, 4, 5, 7))), Vector4i(5, 2, 7, 4)); } -void SwizzleTest::constants() { - CORRADE_COMPARE((swizzle<'1', 'w', '0', 'g'>(Vector4i(2, 4, 5, 7))), Vector4i(1, 7, 0, 4)); -} - -void SwizzleTest::fromSmall() { - CORRADE_COMPARE((swizzle<'g', 'x', 'r'>(Vector2i(1, 2))), Vector3i(2, 1, 1)); -} - void SwizzleTest::type() { Vector4i orig; CORRADE_VERIFY((std::is_same(orig)), Vector2i>::value)); diff --git a/src/Test/SwizzleTest.h b/src/Test/SwizzleTest.h index d9b581517..e432ed9ec 100644 --- a/src/Test/SwizzleTest.h +++ b/src/Test/SwizzleTest.h @@ -23,10 +23,7 @@ class SwizzleTest: public Corrade::TestSuite::Tester { public: SwizzleTest(); - void xyzw(); void rgba(); - void constants(); - void fromSmall(); void type(); void defaultType(); };