From 949b092a60d68af15b67e3e58858f42408f99ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Sep 2012 18:49:35 +0200 Subject: [PATCH] Support for '0' and '1' constants in swizzle() functions. Also deconfused related documentation a bit. --- doc/matrix-vector.dox | 6 +-- src/Swizzle.h | 84 ++++++++++++++++++++++------------------ src/Test/SwizzleTest.cpp | 8 ++++ src/Test/SwizzleTest.h | 1 + 4 files changed, 59 insertions(+), 40 deletions(-) diff --git a/doc/matrix-vector.dox b/doc/matrix-vector.dox index 795f5619c..6b05b00c3 100644 --- a/doc/matrix-vector.dox +++ b/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 compile-time, while the second has more convenient syntax: @code -Vector4 original(1, 2, 3, 4); -Vector4 bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, 1, 4 } -Vector<6, int> a10rgb = swizzle(original, "a10rgb"); // { 4, 1, 0, 1, 2, 3 } +Vector4 original(-1, 2, 3, 4); +Vector4 bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, -1, 4 } +Vector<6, int> a10rgb = swizzle(original, "a10rgb"); // { 4, 1, 0, -1, 2, 3 } @endcode @section matrix-vector-column-major Matrices are column-major and vectors are columns diff --git a/src/Swizzle.h b/src/Swizzle.h index d61ae1cdb..cc57ca072 100644 --- a/src/Swizzle.h +++ b/src/Swizzle.h @@ -28,21 +28,27 @@ namespace Implementation { using Math::Implementation::Sequence; using Math::Implementation::GenerateSequence; - template struct GetPosition { + template struct ComponentAtPosition { static_assert(size > position, "Swizzle parameter out of range of base vector"); - inline constexpr static size_t value() { return position; } + template inline constexpr static T value(const Math::Vector& vector) { return vector[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 Component {}; + template struct Component: public ComponentAtPosition {}; + template struct Component: public ComponentAtPosition {}; + template struct Component: public ComponentAtPosition {}; + template struct Component: public ComponentAtPosition {}; + 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); } + }; template struct TypeForSize { typedef Math::Vector Type; @@ -55,24 +61,26 @@ namespace Implementation { template struct TypeForSize<4, Color3> { typedef Color4 Type; }; template struct TypeForSize<4, Color4> { typedef Color4 Type; }; - inline constexpr size_t getPosition(size_t size, size_t position) { - return size > position ? position : throw; + template inline constexpr T componentAtPosition(const Math::Vector& vector, size_t position) { + return size > position ? vector[position] : throw; } - template inline constexpr size_t getComponent(char component) { - return component == 'x' ? getPosition(size, 0) : - component == 'y' ? getPosition(size, 1) : - component == 'z' ? getPosition(size, 2) : - component == 'w' ? getPosition(size, 3) : - component == 'r' ? getPosition(size, 0) : - component == 'g' ? getPosition(size, 1) : - component == 'b' ? getPosition(size, 2) : - component == 'a' ? getPosition(size, 3) : + template inline constexpr T component(const Math::Vector& vector, char component) { + return component == 'x' ? componentAtPosition(vector, 0) : + component == 'y' ? componentAtPosition(vector, 1) : + component == 'z' ? componentAtPosition(vector, 2) : + component == 'w' ? componentAtPosition(vector, 3) : + component == 'r' ? componentAtPosition(vector, 0) : + component == 'g' ? componentAtPosition(vector, 1) : + component == 'b' ? componentAtPosition(vector, 2) : + component == 'a' ? componentAtPosition(vector, 3) : + component == '0' ? T(0) : + component == '1' ? T(1) : throw; } template inline constexpr Math::Vector swizzleFrom(Sequence, const Math::Vector& vector, const char(&components)[sizeof...(sequence)+1]) { - return {vector[getComponent(components[sequence])]...}; + return {component(vector, components[sequence])...}; } } #endif @@ -82,14 +90,15 @@ namespace Implementation { Creates new vector from given components. Example: @code -Vector4 original(1, 2, 3, 4); +Vector4 original(-1, 2, 3, 4); -auto vec = swizzle<'a', 'b', 'b', 'g', 'r', 'r'>(original); -// vec == { 4, 3, 3, 2, 1, 1 } +auto vec = swizzle<'a', '1', '0', 'r', 'g', 'b'>(original); +// vec == { 4, 1, 0, -1, 2, 3 } @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 +You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a` for addressing +components or letters `0` and `1` for zero and one. Count of elements is +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. @attention This function is less convenient to write than @@ -101,7 +110,7 @@ instead of at runtime. Vector4::xy(), Vector3::xy() */ template inline constexpr typename Implementation::TypeForSize::Type swizzle(const T& vector) { - return {vector[Implementation::GetComponent::value()]...}; + return {Implementation::Component::value(vector)...}; } /** @@ -109,15 +118,16 @@ template inline constexpr typename Implementation:: Creates new vector from given components. Example: @code -Vector4 original(1, 2, 3, 4); +Vector4 original(-1, 2, 3, 4); -auto vec = swizzle(original, "abbgrr"); -// vec == { 4, 3, 3, 2, 1, 1 } +auto vec = swizzle(original, "a10rgb"); +// vec == { 4, 1, 0, -1, 2, 3 } @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. +You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a` for addressing +components or letters `0` and `1` for zero and one. 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. @attention This function is more convenient to write than swizzle(const T&), but unless the result is marked with diff --git a/src/Test/SwizzleTest.cpp b/src/Test/SwizzleTest.cpp index 561b53fcf..4f57462a8 100644 --- a/src/Test/SwizzleTest.cpp +++ b/src/Test/SwizzleTest.cpp @@ -30,6 +30,7 @@ typedef Math::Vector4 Vector4; SwizzleTest::SwizzleTest() { addTests(&SwizzleTest::xyzw, &SwizzleTest::rgba, + &SwizzleTest::constants, &SwizzleTest::fromSmall, &SwizzleTest::type, &SwizzleTest::defaultType); @@ -49,6 +50,13 @@ void SwizzleTest::rgba() { 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() { /* Force compile-time evaluation for both */ constexpr Vector2 orig(1, 2); diff --git a/src/Test/SwizzleTest.h b/src/Test/SwizzleTest.h index b43180be0..56a705f5d 100644 --- a/src/Test/SwizzleTest.h +++ b/src/Test/SwizzleTest.h @@ -25,6 +25,7 @@ class SwizzleTest: public Corrade::TestSuite::Tester { void xyzw(); void rgba(); + void constants(); void fromSmall(); void type(); void defaultType();