Browse Source

New function for vector component swizzling.

vectorfields
Vladimír Vondruš 14 years ago
parent
commit
fff22d0822
  1. 77
      src/Math/Swizzle.h
  2. 2
      src/Math/Test/CMakeLists.txt
  3. 62
      src/Math/Test/SwizzleTest.cpp
  4. 34
      src/Math/Test/SwizzleTest.h
  5. 2
      src/Math/Vector3.h
  6. 6
      src/Math/Vector4.h

77
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š <mosra@centrum.cz>
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<size_t size, size_t position> struct GetPosition {
static_assert(size > position, "Swizzle parameter out of range of base vector");
inline constexpr static size_t value() { return position; }
};
template<size_t size, char component> struct GetComponent {};
template<size_t size> struct GetComponent<size, 'x'>: public GetPosition<size, 0> {};
template<size_t size> struct GetComponent<size, 'y'>: public GetPosition<size, 1> {};
template<size_t size> struct GetComponent<size, 'z'>: public GetPosition<size, 2> {};
template<size_t size> struct GetComponent<size, 'w'>: public GetPosition<size, 3> {};
template<size_t size> struct GetComponent<size, 'r'>: public GetPosition<size, 0> {};
template<size_t size> struct GetComponent<size, 'g'>: public GetPosition<size, 1> {};
template<size_t size> struct GetComponent<size, 'b'>: public GetPosition<size, 2> {};
template<size_t size> struct GetComponent<size, 'a'>: public GetPosition<size, 3> {};
template<size_t size, class T> struct TypeForSize {
typedef Vector<size, T> Type;
};
template<class T> struct TypeForSize<2, T> { typedef Vector2<T> Type; };
template<class T> struct TypeForSize<3, T> { typedef Vector3<T> Type; };
template<class T> struct TypeForSize<4, T> { typedef Vector4<T> Type; };
}
#endif
/**
@brief Swizzle Vector components
Creates new vector from given components. Example:
@code
Vector4<int> 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<char ...components, size_t size, class T> inline constexpr typename Implementation::TypeForSize<sizeof...(components), T>::Type swizzle(const Vector<size, T>& vector) {
return {vector[Implementation::GetComponent<size, components>::value()]...};
}
}}
#endif

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

62
src/Math/Test/SwizzleTest.cpp

@ -0,0 +1,62 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
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<int> Vector2;
typedef Math::Vector3<int> Vector3;
typedef Math::Vector4<int> Vector4;
template<size_t size> using Vector = Math::Vector<size, int>;
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<decltype(swizzle<'y', 'a'>(orig)), Vector2>::value));
CORRADE_VERIFY((is_same<decltype(swizzle<'y', 'z', 'a'>(orig)), Vector3>::value));
CORRADE_VERIFY((is_same<decltype(swizzle<'y', 'a', 'y', 'x'>(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));
}
}}}

34
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š <mosra@centrum.cz>
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 <TestSuite/Tester.h>
namespace Magnum { namespace Math { namespace Test {
class SwizzleTest: public Corrade::TestSuite::Tester<SwizzleTest> {
public:
SwizzleTest();
void xyzw();
void rgba();
void type();
void defaultType();
};
}}}
#endif

2
src/Math/Vector3.h

@ -81,6 +81,8 @@ template<class T> class Vector3: public Vector<3, T> {
/**
* @brief XY part of the vector
* @return First two components of the vector
*
* @see swizzle()
*/
inline constexpr Vector2<T> xy() const { return Vector2<T>::from(Vector<3, T>::data()); }

6
src/Math/Vector4.h

@ -70,12 +70,16 @@ template<class T> class Vector4: public Vector<4, T> {
/**
* @brief XYZ part of the vector
* @return First three components of the vector
*
* @see swizzle()
*/
inline constexpr Vector3<T> xyz() const { return Vector3<T>::from(Vector<4, T>::data()); }
/**
* @brief XY part of the vector
* @return First two components of the vector
*
* @see swizzle()
*/
inline constexpr Vector2<T> xy() const { return Vector2<T>::from(Vector<4, T>::data()); }
@ -92,6 +96,8 @@ template<class T> class Vector4: public Vector<4, T> {
/**
* @brief RGB part of the vector
* @return First three components of the vector
*
* @see swizzle()
*/
inline constexpr Vector3<T> rgb() const { return xyz(); }

Loading…
Cancel
Save