Implement swizzles
This commit is contained in:
parent
7024d9b5a8
commit
4ca37f3d5c
|
@ -0,0 +1,196 @@
|
|||
#pragma once
|
||||
|
||||
#include <Orange/Core/Array.h>
|
||||
|
||||
namespace orange
|
||||
{
|
||||
|
||||
template <typename T, size_t Alignment, size_t Size>
|
||||
struct alignas(Alignment) Swizzle
|
||||
{
|
||||
Array<T, Size> 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 <typename T, size_t Alignment>
|
||||
struct alignas(Alignment) Swizzle<T, Alignment, 1>
|
||||
{
|
||||
union
|
||||
{
|
||||
Array<T, 1> 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 <typename... Args>
|
||||
constexpr Swizzle(const Args&... args)
|
||||
: data {{ args... }}
|
||||
{
|
||||
static_assert(sizeof...(Args) == 1);
|
||||
}
|
||||
|
||||
constexpr Swizzle(const Swizzle& other) = default;
|
||||
};
|
||||
|
||||
template <typename T, size_t Alignment>
|
||||
struct alignas(Alignment) Swizzle<T, Alignment, 2>
|
||||
{
|
||||
union
|
||||
{
|
||||
Array<T, 2> 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 <typename... Args>
|
||||
constexpr Swizzle(const Args&... args)
|
||||
: data {{ args... }}
|
||||
{
|
||||
static_assert(sizeof...(Args) == 2);
|
||||
}
|
||||
|
||||
constexpr Swizzle(const Swizzle& other) = default;
|
||||
};
|
||||
|
||||
template <typename T, size_t Alignment>
|
||||
struct alignas(Alignment) Swizzle<T, Alignment, 3>
|
||||
{
|
||||
union
|
||||
{
|
||||
Array<T, 3> 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 <typename... Args>
|
||||
constexpr Swizzle(const Args&... args)
|
||||
: data {{ args... }}
|
||||
{
|
||||
static_assert(sizeof...(Args) == 3);
|
||||
}
|
||||
|
||||
constexpr Swizzle(const Swizzle& other) = default;
|
||||
};
|
||||
|
||||
template <typename T, size_t Alignment>
|
||||
struct alignas(Alignment) Swizzle<T, Alignment, 4>
|
||||
{
|
||||
union
|
||||
{
|
||||
Array<T, 4> 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 <typename... Args>
|
||||
constexpr Swizzle(const Args&... args)
|
||||
: data {{ args... }}
|
||||
{
|
||||
static_assert(sizeof...(Args) == 4);
|
||||
}
|
||||
|
||||
constexpr Swizzle(const Swizzle& other) = default;
|
||||
};
|
||||
|
||||
}
|
|
@ -5,46 +5,38 @@
|
|||
#include <Orange/Core/Array.h>
|
||||
|
||||
#include <Orange/Math/Basic.h>
|
||||
#include <Orange/Math/Swizzle.h>
|
||||
|
||||
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 <typename T, size_t Size>
|
||||
struct Vec
|
||||
struct VectorAlignmentHelper
|
||||
{
|
||||
static constexpr size_t Alignment =
|
||||
(Size % 4zu == 0 && sizeof(T) == 4zu)
|
||||
? Max<size_t>(16zu, alignof(T))
|
||||
: alignof(T);
|
||||
};
|
||||
|
||||
template <typename T, size_t Size>
|
||||
struct Vec : public Swizzle<T, VectorAlignmentHelper<T, Size>::Alignment, Size>
|
||||
{
|
||||
static constexpr size_t Alignment = VectorAlignmentHelper<T, Size>::Alignment;
|
||||
using DefaultLengthType = DefaultLengthTypeResolver<T>::LengthType;
|
||||
using DefaultLengthVec = Vec<DefaultLengthType, Size>;
|
||||
|
||||
constexpr Vec()
|
||||
: data{ } {}
|
||||
using Swizzle<T, Alignment, Size>::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 <typename... Args>
|
||||
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<size_t>(16zu, alignof(T))
|
||||
: alignof(T);
|
||||
|
||||
union
|
||||
{
|
||||
alignas(Alignment) Array<T, Size> data;
|
||||
struct
|
||||
{
|
||||
alignas(Alignment) float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template <typename T, size_t Size>
|
||||
|
|
Loading…
Reference in New Issue