|
|
|
|
@ -34,27 +34,27 @@
|
|
|
|
|
namespace Magnum { namespace Math { |
|
|
|
|
|
|
|
|
|
namespace Implementation { |
|
|
|
|
template<std::size_t size, std::size_t position> struct ComponentAtPosition { |
|
|
|
|
static_assert(size > position, "swizzle parameter out of range of gather vector"); |
|
|
|
|
template<std::size_t size, std::size_t position> struct GatherComponentAt { |
|
|
|
|
static_assert(size > position, "numeric swizzle parameter out of range of gather vector, use either xyzw/rgba/0/1 letters or small enough numbers"); |
|
|
|
|
|
|
|
|
|
template<class T> constexpr static T value(const Math::Vector<size, T>& vector) { |
|
|
|
|
return vector._data[position]; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
template<std::size_t size, char component> struct Component {}; |
|
|
|
|
template<std::size_t size> struct Component<size, 'x'>: public ComponentAtPosition<size, 0> {}; |
|
|
|
|
template<std::size_t size> struct Component<size, 'y'>: public ComponentAtPosition<size, 1> {}; |
|
|
|
|
template<std::size_t size> struct Component<size, 'z'>: public ComponentAtPosition<size, 2> {}; |
|
|
|
|
template<std::size_t size> struct Component<size, 'w'>: public ComponentAtPosition<size, 3> {}; |
|
|
|
|
template<std::size_t size> struct Component<size, 'r'>: public ComponentAtPosition<size, 0> {}; |
|
|
|
|
template<std::size_t size> struct Component<size, 'g'>: public ComponentAtPosition<size, 1> {}; |
|
|
|
|
template<std::size_t size> struct Component<size, 'b'>: public ComponentAtPosition<size, 2> {}; |
|
|
|
|
template<std::size_t size> struct Component<size, 'a'>: public ComponentAtPosition<size, 3> {}; |
|
|
|
|
template<std::size_t size> struct Component<size, '0'> { |
|
|
|
|
template<std::size_t size, char component> struct GatherComponent: GatherComponentAt<size, component> {}; |
|
|
|
|
template<std::size_t size> struct GatherComponent<size, 'x'>: public GatherComponentAt<size, 0> {}; |
|
|
|
|
template<std::size_t size> struct GatherComponent<size, 'y'>: public GatherComponentAt<size, 1> {}; |
|
|
|
|
template<std::size_t size> struct GatherComponent<size, 'z'>: public GatherComponentAt<size, 2> {}; |
|
|
|
|
template<std::size_t size> struct GatherComponent<size, 'w'>: public GatherComponentAt<size, 3> {}; |
|
|
|
|
template<std::size_t size> struct GatherComponent<size, 'r'>: public GatherComponentAt<size, 0> {}; |
|
|
|
|
template<std::size_t size> struct GatherComponent<size, 'g'>: public GatherComponentAt<size, 1> {}; |
|
|
|
|
template<std::size_t size> struct GatherComponent<size, 'b'>: public GatherComponentAt<size, 2> {}; |
|
|
|
|
template<std::size_t size> struct GatherComponent<size, 'a'>: public GatherComponentAt<size, 3> {}; |
|
|
|
|
template<std::size_t size> struct GatherComponent<size, '0'> { |
|
|
|
|
template<class T> constexpr static T value(const Math::Vector<size, T>&) { return T(0); } |
|
|
|
|
}; |
|
|
|
|
template<std::size_t size> struct Component<size, '1'> { |
|
|
|
|
template<std::size_t size> struct GatherComponent<size, '1'> { |
|
|
|
|
template<class T> constexpr static T value(const Math::Vector<size, T>&) { return T(1); } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
@ -62,40 +62,42 @@ namespace Implementation {
|
|
|
|
|
typedef Math::Vector<size, typename T::Type> Type; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
template<std::size_t size, char component, std::size_t i> struct ComponentOr { |
|
|
|
|
static_assert(component == 'x' || component == 'r' || |
|
|
|
|
((component == 'y' || component == 'g') && size > 1) || |
|
|
|
|
((component == 'z' || component == 'b') && size > 2) || |
|
|
|
|
((component == 'w' || component == 'a') && size > 3), |
|
|
|
|
"swizzle parameter out of range of scatter vector"); |
|
|
|
|
|
|
|
|
|
template<std::size_t size, std::size_t i, bool = true> struct ScatterComponentOr { |
|
|
|
|
template<class T> constexpr static T value(const Math::Vector<size, T>&, const T& value) { |
|
|
|
|
return value; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
template<std::size_t size, std::size_t i> struct ScatterComponentOr<size, i, false> { |
|
|
|
|
template<class T> constexpr static T value(const Math::Vector<size, T>& vector, const T&) { |
|
|
|
|
return vector._data[i]; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
template<std::size_t size, std::size_t position> struct Value { |
|
|
|
|
template<class T> constexpr static T value(const Math::Vector<size, T>&, const T& value) { |
|
|
|
|
return value; |
|
|
|
|
} |
|
|
|
|
template<std::size_t size, char component, std::size_t i> struct ScatterComponent: ScatterComponentOr<size, i, component == i> { |
|
|
|
|
static_assert(component == 'x' || component == 'r' || |
|
|
|
|
((component == 'y' || component == 'g') && size > 1) || |
|
|
|
|
((component == 'z' || component == 'b') && size > 2) || |
|
|
|
|
((component == 'w' || component == 'a') && size > 3) || |
|
|
|
|
std::size_t(component) < size, |
|
|
|
|
"swizzle parameter out of range of scatter vector, use either xyzw/rgba letters or small enough numbers"); |
|
|
|
|
}; |
|
|
|
|
template<std::size_t size> struct ComponentOr<size, 'x', 0>: Value<size, 0> {}; |
|
|
|
|
template<std::size_t size> struct ComponentOr<size, 'y', 1>: Value<size, 1> {}; |
|
|
|
|
template<std::size_t size> struct ComponentOr<size, 'z', 2>: Value<size, 2> {}; |
|
|
|
|
template<std::size_t size> struct ComponentOr<size, 'w', 3>: Value<size, 3> {}; |
|
|
|
|
template<std::size_t size> struct ComponentOr<size, 'r', 0>: Value<size, 0> {}; |
|
|
|
|
template<std::size_t size> struct ComponentOr<size, 'g', 1>: Value<size, 1> {}; |
|
|
|
|
template<std::size_t size> struct ComponentOr<size, 'b', 2>: Value<size, 2> {}; |
|
|
|
|
template<std::size_t size> struct ComponentOr<size, 'a', 3>: Value<size, 3> {}; |
|
|
|
|
|
|
|
|
|
template<class T, char component, std::size_t ...sequence> constexpr T componentOr(const T& vector, const typename T::Type& value, Sequence<sequence...>) { |
|
|
|
|
return {ComponentOr<T::Size, component, sequence>::value(vector, value)...}; |
|
|
|
|
template<std::size_t size> struct ScatterComponent<size, 'x', 0>: ScatterComponentOr<size, 0> {}; |
|
|
|
|
template<std::size_t size> struct ScatterComponent<size, 'y', 1>: ScatterComponentOr<size, 1> {}; |
|
|
|
|
template<std::size_t size> struct ScatterComponent<size, 'z', 2>: ScatterComponentOr<size, 2> {}; |
|
|
|
|
template<std::size_t size> struct ScatterComponent<size, 'w', 3>: ScatterComponentOr<size, 3> {}; |
|
|
|
|
template<std::size_t size> struct ScatterComponent<size, 'r', 0>: ScatterComponentOr<size, 0> {}; |
|
|
|
|
template<std::size_t size> struct ScatterComponent<size, 'g', 1>: ScatterComponentOr<size, 1> {}; |
|
|
|
|
template<std::size_t size> struct ScatterComponent<size, 'b', 2>: ScatterComponentOr<size, 2> {}; |
|
|
|
|
template<std::size_t size> struct ScatterComponent<size, 'a', 3>: ScatterComponentOr<size, 3> {}; |
|
|
|
|
|
|
|
|
|
template<class T, char component, std::size_t ...sequence> constexpr T scatterComponentOr(const T& vector, const typename T::Type& value, Sequence<sequence...>) { |
|
|
|
|
return {ScatterComponent<T::Size, component, sequence>::value(vector, value)...}; |
|
|
|
|
} |
|
|
|
|
template<class T, std::size_t valueSize> constexpr T scatterRecursive(const T& vector, const Math::Vector<valueSize, typename T::Type>&, std::size_t) { |
|
|
|
|
template<class T, std::size_t valueSize> constexpr T scatterRecursive(const T& vector, const Vector<valueSize, typename T::Type>&, std::size_t) { |
|
|
|
|
return vector; |
|
|
|
|
} |
|
|
|
|
template<class T, std::size_t valueSize, char component, char ...next> constexpr T scatterRecursive(const T& vector, const Math::Vector<valueSize, typename T::Type>& values, std::size_t valueIndex) { |
|
|
|
|
template<class T, std::size_t valueSize, char component, char ...next> constexpr T scatterRecursive(const T& vector, const Vector<valueSize, typename T::Type>& values, std::size_t valueIndex) { |
|
|
|
|
return scatterRecursive<T, valueSize, next...>( |
|
|
|
|
componentOr<T, component>(vector, values[valueIndex], typename GenerateSequence<T::Size>::Type{}), |
|
|
|
|
scatterComponentOr<T, component>(vector, values[valueIndex], typename GenerateSequence<T::Size>::Type{}), |
|
|
|
|
values, valueIndex + 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -109,8 +111,10 @@ Creates a new vector from given components. Example:
|
|
|
|
|
|
|
|
|
|
You can use letters @cpp 'x' @ce, @cpp 'y' @ce, @cpp 'z' @ce, @cpp 'w' @ce and |
|
|
|
|
@cpp 'r' @ce, @cpp 'g' @ce, @cpp 'b' @ce, @cpp 'a' @ce for addressing |
|
|
|
|
components or letters @cpp '0' @ce and @cpp '1' @ce for zero and one. Count of |
|
|
|
|
elements is unlimited, but must be at least one. If the resulting vector is |
|
|
|
|
components or letters @cpp '0' @ce and @cpp '1' @ce for zero and one. |
|
|
|
|
Alternatively you can also address components using their numeric index --- |
|
|
|
|
which is especially useful when your input has more than four components. Count |
|
|
|
|
of elements is unlimited, but must be at least one. If the resulting vector is |
|
|
|
|
two, three or four-component, corresponding @ref Vector2, @ref Vector3, |
|
|
|
|
@ref Vector4, @ref Color3 or @ref Color4 specialization is returned. |
|
|
|
|
|
|
|
|
|
@ -118,7 +122,7 @@ two, three or four-component, corresponding @ref Vector2, @ref Vector3,
|
|
|
|
|
@ref Vector4::rgb(), @ref Vector4::xy(), @ref Vector3::xy() |
|
|
|
|
*/ |
|
|
|
|
template<char ...components, class T> constexpr typename Implementation::TypeForSize<sizeof...(components), T>::Type gather(const T& vector) { |
|
|
|
|
return {Implementation::Component<T::Size, components>::value(vector)...}; |
|
|
|
|
return {Implementation::GatherComponent<T::Size, components>::value(vector)...}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|