diff --git a/src/Math/Swizzle.h b/src/Math/Swizzle.h new file mode 100644 index 000000000..cfbec9290 --- /dev/null +++ b/src/Math/Swizzle.h @@ -0,0 +1,77 @@ +#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 "Vector4.h" + +namespace Magnum { namespace Math { + +#ifndef DOXYGEN_GENERATING_OUTPUT +namespace Implementation { + template struct GetPosition { + static_assert(size > position, "Swizzle parameter out of range of base vector"); + + inline constexpr static size_t value() { return position; } + }; + + template struct GetComponent {}; + template struct GetComponent: public GetPosition {}; + template struct GetComponent: public GetPosition {}; + template struct GetComponent: public GetPosition {}; + template struct GetComponent: public GetPosition {}; + template struct GetComponent: public GetPosition {}; + template struct GetComponent: public GetPosition {}; + template struct GetComponent: public GetPosition {}; + template struct GetComponent: public GetPosition {}; + + template struct TypeForSize { + typedef Vector Type; + }; + + template struct TypeForSize<2, T> { typedef Vector2 Type; }; + template struct TypeForSize<3, T> { typedef Vector3 Type; }; + template struct TypeForSize<4, T> { typedef Vector4 Type; }; +} +#endif + +/** +@brief Swizzle Vector components + +Creates new vector from given components. Example: +@code +Vector4 original(1, 2, 3, 4); + +auto vec = swizzle<'a', 'b', 'b', 'g', 'r', 'r'>(original); +// vec == { 4, 3, 3, 2, 1, 1 } +@endcode +You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a`. Count of +elements is unlimited, but must be at least one. If the resulting vector is +two, three or four-component, corresponding Vector2, Vector3 or Vector4 +specialization is returned. + +@see Vector4::xyz(), Vector4::rgb(), Vector4::xy(), Vector3::xy() +*/ +template inline constexpr typename Implementation::TypeForSize::Type swizzle(const Vector& vector) { + return {vector[Implementation::GetComponent::value()]...}; +} + +}} + +#endif diff --git a/src/Math/Test/CMakeLists.txt b/src/Math/Test/CMakeLists.txt index 9c96b0ccb..d19e1d975 100644 --- a/src/Math/Test/CMakeLists.txt +++ b/src/Math/Test/CMakeLists.txt @@ -5,6 +5,8 @@ corrade_add_test2(MathVector2Test Vector2Test.cpp) corrade_add_test2(MathVector3Test Vector3Test.cpp) corrade_add_test2(MathVector4Test Vector4Test.cpp) +corrade_add_test2(MathSwizzleTest SwizzleTest.cpp) + corrade_add_test2(MathMatrixTest MatrixTest.cpp) corrade_add_test2(MathMatrix3Test Matrix3Test.cpp) corrade_add_test2(MathMatrix4Test Matrix4Test.cpp) diff --git a/src/Math/Test/SwizzleTest.cpp b/src/Math/Test/SwizzleTest.cpp new file mode 100644 index 000000000..f71cc8d6d --- /dev/null +++ b/src/Math/Test/SwizzleTest.cpp @@ -0,0 +1,62 @@ +/* + 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 "Swizzle.h" + +using namespace std; + +CORRADE_TEST_MAIN(Magnum::Math::Test::SwizzleTest) + +namespace Magnum { namespace Math { namespace Test { + +typedef Math::Vector2 Vector2; +typedef Math::Vector3 Vector3; +typedef Math::Vector4 Vector4; + +template using Vector = Math::Vector; + +SwizzleTest::SwizzleTest() { + addTests(&SwizzleTest::xyzw, + &SwizzleTest::rgba, + &SwizzleTest::type, + &SwizzleTest::defaultType); +} + +void SwizzleTest::xyzw() { + Vector4 orig(2, 4, 5, 7); + CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y'>(orig)), Vector4(5, 2, 7, 4)); +} + +void SwizzleTest::rgba() { + Vector4 orig(2, 4, 5, 7); + CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g'>(orig)), Vector4(5, 2, 7, 4)); +} + +void SwizzleTest::type() { + Vector4 orig; + CORRADE_VERIFY((is_same(orig)), Vector2>::value)); + CORRADE_VERIFY((is_same(orig)), Vector3>::value)); + CORRADE_VERIFY((is_same(orig)), Vector4>::value)); +} + +void SwizzleTest::defaultType() { + Vector4 orig(1, 2, 3, 4); + CORRADE_COMPARE(swizzle<'b'>(orig), Vector<1>(3)); + CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g', 'z', 'y', 'x'>(orig)), Vector<7>(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..f68a05e45 --- /dev/null +++ b/src/Math/Test/SwizzleTest.h @@ -0,0 +1,34 @@ +#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 xyzw(); + void rgba(); + void type(); + void defaultType(); +}; + +}}} + +#endif diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index e9b691914..30072d7f5 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -81,6 +81,8 @@ template class Vector3: public Vector<3, T> { /** * @brief XY part of the vector * @return First two components of the vector + * + * @see swizzle() */ inline constexpr Vector2 xy() const { return Vector2::from(Vector<3, T>::data()); } diff --git a/src/Math/Vector4.h b/src/Math/Vector4.h index a447bfac4..c406ef19b 100644 --- a/src/Math/Vector4.h +++ b/src/Math/Vector4.h @@ -70,12 +70,16 @@ template class Vector4: public Vector<4, T> { /** * @brief XYZ part of the vector * @return First three components of the vector + * + * @see swizzle() */ inline constexpr Vector3 xyz() const { return Vector3::from(Vector<4, T>::data()); } /** * @brief XY part of the vector * @return First two components of the vector + * + * @see swizzle() */ inline constexpr Vector2 xy() const { return Vector2::from(Vector<4, T>::data()); } @@ -92,6 +96,8 @@ template class Vector4: public Vector<4, T> { /** * @brief RGB part of the vector * @return First three components of the vector + * + * @see swizzle() */ inline constexpr Vector3 rgb() const { return xyz(); }