Browse Source

Support for '0' and '1' constants in swizzle() functions.

Also deconfused related documentation a bit.
pull/279/head
Vladimír Vondruš 14 years ago
parent
commit
949b092a60
  1. 6
      doc/matrix-vector.dox
  2. 84
      src/Swizzle.h
  3. 8
      src/Test/SwizzleTest.cpp
  4. 1
      src/Test/SwizzleTest.h

6
doc/matrix-vector.dox

@ -138,9 +138,9 @@ For more involved operations with components there are two swizzle() functions,
they have the same features, but one is guaranteed to do most of the work at they have the same features, but one is guaranteed to do most of the work at
compile-time, while the second has more convenient syntax: compile-time, while the second has more convenient syntax:
@code @code
Vector4<int> original(1, 2, 3, 4); Vector4<int> original(-1, 2, 3, 4);
Vector4<int> bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, 1, 4 } Vector4<int> bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, -1, 4 }
Vector<6, int> a10rgb = swizzle(original, "a10rgb"); // { 4, 1, 0, 1, 2, 3 } Vector<6, int> a10rgb = swizzle(original, "a10rgb"); // { 4, 1, 0, -1, 2, 3 }
@endcode @endcode
@section matrix-vector-column-major Matrices are column-major and vectors are columns @section matrix-vector-column-major Matrices are column-major and vectors are columns

84
src/Swizzle.h

@ -28,21 +28,27 @@ namespace Implementation {
using Math::Implementation::Sequence; using Math::Implementation::Sequence;
using Math::Implementation::GenerateSequence; using Math::Implementation::GenerateSequence;
template<size_t size, size_t position> struct GetPosition { template<size_t size, size_t position> struct ComponentAtPosition {
static_assert(size > position, "Swizzle parameter out of range of base vector"); static_assert(size > position, "Swizzle parameter out of range of base vector");
inline constexpr static size_t value() { return position; } template<class T> inline constexpr static T value(const Math::Vector<size, T>& vector) { return vector[position]; }
}; };
template<size_t size, char component> struct GetComponent {}; template<size_t size, char component> struct Component {};
template<size_t size> struct GetComponent<size, 'x'>: public GetPosition<size, 0> {}; template<size_t size> struct Component<size, 'x'>: public ComponentAtPosition<size, 0> {};
template<size_t size> struct GetComponent<size, 'y'>: public GetPosition<size, 1> {}; template<size_t size> struct Component<size, 'y'>: public ComponentAtPosition<size, 1> {};
template<size_t size> struct GetComponent<size, 'z'>: public GetPosition<size, 2> {}; template<size_t size> struct Component<size, 'z'>: public ComponentAtPosition<size, 2> {};
template<size_t size> struct GetComponent<size, 'w'>: public GetPosition<size, 3> {}; template<size_t size> struct Component<size, 'w'>: public ComponentAtPosition<size, 3> {};
template<size_t size> struct GetComponent<size, 'r'>: public GetPosition<size, 0> {}; template<size_t size> struct Component<size, 'r'>: public ComponentAtPosition<size, 0> {};
template<size_t size> struct GetComponent<size, 'g'>: public GetPosition<size, 1> {}; template<size_t size> struct Component<size, 'g'>: public ComponentAtPosition<size, 1> {};
template<size_t size> struct GetComponent<size, 'b'>: public GetPosition<size, 2> {}; template<size_t size> struct Component<size, 'b'>: public ComponentAtPosition<size, 2> {};
template<size_t size> struct GetComponent<size, 'a'>: public GetPosition<size, 3> {}; template<size_t size> struct Component<size, 'a'>: public ComponentAtPosition<size, 3> {};
template<size_t size> struct Component<size, '0'> {
template<class T> inline constexpr static T value(const Math::Vector<size, T>&) { return T(0); }
};
template<size_t size> struct Component<size, '1'> {
template<class T> inline constexpr static T value(const Math::Vector<size, T>&) { return T(1); }
};
template<size_t size, class T> struct TypeForSize { template<size_t size, class T> struct TypeForSize {
typedef Math::Vector<size, typename T::Type> Type; typedef Math::Vector<size, typename T::Type> Type;
@ -55,24 +61,26 @@ namespace Implementation {
template<class T> struct TypeForSize<4, Color3<T>> { typedef Color4<T> Type; }; template<class T> struct TypeForSize<4, Color3<T>> { typedef Color4<T> Type; };
template<class T> struct TypeForSize<4, Color4<T>> { typedef Color4<T> Type; }; template<class T> struct TypeForSize<4, Color4<T>> { typedef Color4<T> Type; };
inline constexpr size_t getPosition(size_t size, size_t position) { template<size_t size, class T> inline constexpr T componentAtPosition(const Math::Vector<size, T>& vector, size_t position) {
return size > position ? position : throw; return size > position ? vector[position] : throw;
} }
template<size_t size> inline constexpr size_t getComponent(char component) { template<size_t size, class T> inline constexpr T component(const Math::Vector<size, T>& vector, char component) {
return component == 'x' ? getPosition(size, 0) : return component == 'x' ? componentAtPosition(vector, 0) :
component == 'y' ? getPosition(size, 1) : component == 'y' ? componentAtPosition(vector, 1) :
component == 'z' ? getPosition(size, 2) : component == 'z' ? componentAtPosition(vector, 2) :
component == 'w' ? getPosition(size, 3) : component == 'w' ? componentAtPosition(vector, 3) :
component == 'r' ? getPosition(size, 0) : component == 'r' ? componentAtPosition(vector, 0) :
component == 'g' ? getPosition(size, 1) : component == 'g' ? componentAtPosition(vector, 1) :
component == 'b' ? getPosition(size, 2) : component == 'b' ? componentAtPosition(vector, 2) :
component == 'a' ? getPosition(size, 3) : component == 'a' ? componentAtPosition(vector, 3) :
component == '0' ? T(0) :
component == '1' ? T(1) :
throw; throw;
} }
template<size_t size, class T, size_t ...sequence> inline constexpr Math::Vector<sizeof...(sequence), T> swizzleFrom(Sequence<sequence...>, const Math::Vector<size, T>& vector, const char(&components)[sizeof...(sequence)+1]) { template<size_t size, class T, size_t ...sequence> inline constexpr Math::Vector<sizeof...(sequence), T> swizzleFrom(Sequence<sequence...>, const Math::Vector<size, T>& vector, const char(&components)[sizeof...(sequence)+1]) {
return {vector[getComponent<size>(components[sequence])]...}; return {component<size>(vector, components[sequence])...};
} }
} }
#endif #endif
@ -82,14 +90,15 @@ namespace Implementation {
Creates new vector from given components. Example: Creates new vector from given components. Example:
@code @code
Vector4<int> original(1, 2, 3, 4); Vector4<int> original(-1, 2, 3, 4);
auto vec = swizzle<'a', 'b', 'b', 'g', 'r', 'r'>(original); auto vec = swizzle<'a', '1', '0', 'r', 'g', 'b'>(original);
// vec == { 4, 3, 3, 2, 1, 1 } // vec == { 4, 1, 0, -1, 2, 3 }
@endcode @endcode
You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a`. Count of You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a` for addressing
elements is unlimited, but must be at least one. If the resulting vector is components or letters `0` and `1` for zero and one. Count of elements is
two, three or four-component, corresponding Vector2, Vector3 or Vector4 unlimited, but must be at least one. If the resulting vector is two, three or
four-component, corresponding Vector2, Vector3, Vector4, Color3 or Color4
specialization is returned. specialization is returned.
@attention This function is less convenient to write than @attention This function is less convenient to write than
@ -101,7 +110,7 @@ instead of at runtime.
Vector4::xy(), Vector3::xy() Vector4::xy(), Vector3::xy()
*/ */
template<char ...components, class T> inline constexpr typename Implementation::TypeForSize<sizeof...(components), T>::Type swizzle(const T& vector) { template<char ...components, class T> inline constexpr typename Implementation::TypeForSize<sizeof...(components), T>::Type swizzle(const T& vector) {
return {vector[Implementation::GetComponent<T::size, components>::value()]...}; return {Implementation::Component<T::size, components>::value(vector)...};
} }
/** /**
@ -109,15 +118,16 @@ template<char ...components, class T> inline constexpr typename Implementation::
Creates new vector from given components. Example: Creates new vector from given components. Example:
@code @code
Vector4<int> original(1, 2, 3, 4); Vector4<int> original(-1, 2, 3, 4);
auto vec = swizzle(original, "abbgrr"); auto vec = swizzle(original, "a10rgb");
// vec == { 4, 3, 3, 2, 1, 1 } // vec == { 4, 1, 0, -1, 2, 3 }
@endcode @endcode
You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a`. Count of You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a` for addressing
elements is unlimited, but must be at least one. If the resulting vector is components or letters `0` and `1` for zero and one. Count of elements is
two, three or four-component, corresponding Vector2, Vector3 or Vector4 unlimited, but must be at least one. If the resulting vector is two, three or
specialization is returned. four-component, corresponding Vector2, Vector3 or Vector4 specialization is
returned.
@attention This function is more convenient to write than @attention This function is more convenient to write than
swizzle(const T&), but unless the result is marked with swizzle(const T&), but unless the result is marked with

8
src/Test/SwizzleTest.cpp

@ -30,6 +30,7 @@ typedef Math::Vector4<int> Vector4;
SwizzleTest::SwizzleTest() { SwizzleTest::SwizzleTest() {
addTests(&SwizzleTest::xyzw, addTests(&SwizzleTest::xyzw,
&SwizzleTest::rgba, &SwizzleTest::rgba,
&SwizzleTest::constants,
&SwizzleTest::fromSmall, &SwizzleTest::fromSmall,
&SwizzleTest::type, &SwizzleTest::type,
&SwizzleTest::defaultType); &SwizzleTest::defaultType);
@ -49,6 +50,13 @@ void SwizzleTest::rgba() {
CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g'>(orig)), swizzled); CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g'>(orig)), swizzled);
} }
void SwizzleTest::constants() {
Vector4 orig(2, 4, 5, 7);
Vector4 swizzled(1, 7, 0, 4);
CORRADE_COMPARE(swizzle(orig, "1w0g"), swizzled);
CORRADE_COMPARE((swizzle<'1', 'w', '0', 'g'>(orig)), swizzled);
}
void SwizzleTest::fromSmall() { void SwizzleTest::fromSmall() {
/* Force compile-time evaluation for both */ /* Force compile-time evaluation for both */
constexpr Vector2 orig(1, 2); constexpr Vector2 orig(1, 2);

1
src/Test/SwizzleTest.h

@ -25,6 +25,7 @@ class SwizzleTest: public Corrade::TestSuite::Tester<SwizzleTest> {
void xyzw(); void xyzw();
void rgba(); void rgba();
void constants();
void fromSmall(); void fromSmall();
void type(); void type();
void defaultType(); void defaultType();

Loading…
Cancel
Save