From 4ca37f3d5c9e109a1e27511755d0663bfbb07681 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Sat, 13 Aug 2022 09:39:26 +0000 Subject: [PATCH] Implement swizzles --- include/Orange/Math/Swizzle.h | 196 ++++++++++++++++++++++++++++++++++ include/Orange/Math/Vector.h | 70 ++++-------- 2 files changed, 217 insertions(+), 49 deletions(-) create mode 100644 include/Orange/Math/Swizzle.h diff --git a/include/Orange/Math/Swizzle.h b/include/Orange/Math/Swizzle.h new file mode 100644 index 0000000..2664dfe --- /dev/null +++ b/include/Orange/Math/Swizzle.h @@ -0,0 +1,196 @@ +#pragma once + +#include + +namespace orange +{ + + template + struct alignas(Alignment) Swizzle + { + Array data; + + // TODO: Deduplicate these constructors... somehow + constexpr Swizzle() + : data{ } {} + + constexpr explicit Swizzle(T splat) + { + Fill(data.begin(), data.end(), splat); + } + + constexpr Swizzle(const T components[Size]) + { + Copy(&components[0], &components[Size], data.begin()); + } + }; + + template + struct alignas(Alignment) Swizzle + { + union + { + Array data; + struct + { + float x; + }; + struct + { + float r; + }; + }; + + constexpr Swizzle() + : data{ } {} + + constexpr explicit Swizzle(T splat) + { + Fill(data.begin(), data.end(), splat); + } + + constexpr Swizzle(const T components[1]) + { + Copy(&components[0], &components[1], data.begin()); + } + + template + constexpr Swizzle(const Args&... args) + : data {{ args... }} + { + static_assert(sizeof...(Args) == 1); + } + + constexpr Swizzle(const Swizzle& other) = default; + }; + + template + struct alignas(Alignment) Swizzle + { + union + { + Array data; + struct + { + float x; + float y; + }; + struct + { + float r; + float g; + }; + }; + + constexpr Swizzle() + : data{ } {} + + constexpr explicit Swizzle(T splat) + { + Fill(data.begin(), data.end(), splat); + } + + constexpr Swizzle(const T components[2]) + { + Copy(&components[0], &components[2], data.begin()); + } + + template + constexpr Swizzle(const Args&... args) + : data {{ args... }} + { + static_assert(sizeof...(Args) == 2); + } + + constexpr Swizzle(const Swizzle& other) = default; + }; + + template + struct alignas(Alignment) Swizzle + { + union + { + Array data; + struct + { + float x; + float y; + float z; + }; + struct + { + float r; + float g; + float b; + }; + }; + + constexpr Swizzle() + : data{ } {} + + constexpr explicit Swizzle(T splat) + { + Fill(data.begin(), data.end(), splat); + } + + constexpr Swizzle(const T components[3]) + { + Copy(&components[0], &components[3], data.begin()); + } + + template + constexpr Swizzle(const Args&... args) + : data {{ args... }} + { + static_assert(sizeof...(Args) == 3); + } + + constexpr Swizzle(const Swizzle& other) = default; + }; + + template + struct alignas(Alignment) Swizzle + { + union + { + Array data; + struct + { + float x; + float y; + float z; + float w; + }; + struct + { + float r; + float g; + float b; + float a; + }; + }; + + constexpr Swizzle() + : data{ } {} + + constexpr explicit Swizzle(T splat) + { + Fill(data.begin(), data.end(), splat); + } + + constexpr Swizzle(const T components[4]) + { + Copy(&components[0], &components[4], data.begin()); + } + + template + constexpr Swizzle(const Args&... args) + : data {{ args... }} + { + static_assert(sizeof...(Args) == 4); + } + + constexpr Swizzle(const Swizzle& other) = default; + }; + +} diff --git a/include/Orange/Math/Vector.h b/include/Orange/Math/Vector.h index 7632fb8..2ce4a57 100644 --- a/include/Orange/Math/Vector.h +++ b/include/Orange/Math/Vector.h @@ -5,46 +5,38 @@ #include #include +#include namespace orange { + // Align to 16 if the size is a multiple of 4 and T is 4 bytes in size. + // to take advantage of aligned load/stores. template - struct Vec + struct VectorAlignmentHelper { + static constexpr size_t Alignment = + (Size % 4zu == 0 && sizeof(T) == 4zu) + ? Max(16zu, alignof(T)) + : alignof(T); + }; + + template + struct Vec : public Swizzle::Alignment, Size> + { + static constexpr size_t Alignment = VectorAlignmentHelper::Alignment; using DefaultLengthType = DefaultLengthTypeResolver::LengthType; using DefaultLengthVec = Vec; - constexpr Vec() - : data{ } {} + using Swizzle::Swizzle; - constexpr explicit Vec(T splat) - { - Fill(data.begin(), data.end(), splat); - } - - constexpr Vec(const T components[Size]) - { - Copy(&components[0], &components[Size], data.begin()); - } - - template - constexpr Vec(const Args&... args) - : data {{ args... }} - { - static_assert(sizeof...(Args) == Size); - } - - constexpr Vec(const Vec& other) = default; + constexpr T& operator[](size_t index) { return this->data[index]; } + constexpr const T& operator[](size_t index) const { return this->data[index]; } - constexpr T& operator[](size_t index) { return data[index]; } - constexpr const T& operator[](size_t index) const { return data[index]; } - - - constexpr const T* begin() const { return data.begin(); } - constexpr T* begin() { return data.begin(); } - constexpr const T* end() const { return data.end(); } - constexpr T* end() { return data.end(); } + constexpr const T* begin() const { return this->data.begin(); } + constexpr T* begin() { return this->data.begin(); } + constexpr const T* end() const { return this->data.end(); } + constexpr T* end() { return this->data.end(); } constexpr bool operator==(const Vec& other) const @@ -188,26 +180,6 @@ namespace orange static constexpr Vec Zero = Vec{ T{ 0 } }; static constexpr Vec Identity = Vec{ T{ 1 } }; - - // Align to 16 if the size is a multiple of 4 and T is 4 bytes in size. - // to take advantage of aligned load/stores. - static constexpr size_t Alignment = - (Size % 4zu == 0 && sizeof(T) == 4zu) - ? Max(16zu, alignof(T)) - : alignof(T); - - union - { - alignas(Alignment) Array data; - struct - { - alignas(Alignment) float x; - float y; - float z; - float w; - }; - }; - }; template