coord: use stricter member variable names
use tags for the core coordinate structures to specify what names should be used for the data variables (in the data union)
This commit is contained in:
parent
791b91420f
commit
e5d99b3370
@ -29,8 +29,8 @@
|
|||||||
namespace util {
|
namespace util {
|
||||||
/// An RGBA colour POD type.
|
/// An RGBA colour POD type.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct colour : public detail::coord<4, T> {
|
struct colour : public detail::coord<4,T,detail::rgba> {
|
||||||
using detail::coord<4,T>::coord;
|
using detail::coord<4,T,detail::rgba>::coord;
|
||||||
|
|
||||||
static const colour WHITE;
|
static const colour WHITE;
|
||||||
static const colour BLACK;
|
static const colour BLACK;
|
||||||
|
204
detail/coord.hpp
204
detail/coord.hpp
@ -40,102 +40,180 @@ namespace util {
|
|||||||
#pragma GCC diagnostic ignored "-Wgnu"
|
#pragma GCC diagnostic ignored "-Wgnu"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// tags for accessor names
|
||||||
|
struct rgba { };
|
||||||
|
struct xyzw { };
|
||||||
|
struct stpq { };
|
||||||
|
struct whd { };
|
||||||
|
|
||||||
|
|
||||||
|
template <size_t S, typename T, typename...>
|
||||||
|
struct coord_base {
|
||||||
|
T data[S];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct coord_base<3,T,rgba> {
|
||||||
|
union {
|
||||||
|
T data[3];
|
||||||
|
struct { T r,g,b; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct coord_base<4,T,rgba> {
|
||||||
|
union {
|
||||||
|
T data[4];
|
||||||
|
struct { T r,g,b,a; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct coord_base<2,T,xyzw> {
|
||||||
|
union {
|
||||||
|
T data[2];
|
||||||
|
struct { T x,y; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct coord_base<3,T,xyzw> {
|
||||||
|
union {
|
||||||
|
T data[3];
|
||||||
|
struct { T x,y,z; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct coord_base<4,T,xyzw> {
|
||||||
|
union {
|
||||||
|
T data[4];
|
||||||
|
struct { T x,y,z,w; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct coord_base<2,T,xyzw,stpq> {
|
||||||
|
union {
|
||||||
|
T data[2];
|
||||||
|
struct { T x,y; };
|
||||||
|
struct { T s,t; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct coord_base<3,T,xyzw,stpq> {
|
||||||
|
union {
|
||||||
|
T data[3];
|
||||||
|
struct { T x,y,z; };
|
||||||
|
struct { T s,t,p; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct coord_base<4,T,xyzw,stpq> {
|
||||||
|
union {
|
||||||
|
T data[4];
|
||||||
|
struct { T x,y,z,w; };
|
||||||
|
struct { T s,t,p,q; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct coord_base<2,T,whd> {
|
||||||
|
union {
|
||||||
|
T data[2];
|
||||||
|
struct { T w,h; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct coord_base<3,T,whd> {
|
||||||
|
union {
|
||||||
|
T data[3];
|
||||||
|
struct { T w,h,d; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// coord types are not really intended to have arbitrary dimension, so
|
// coord types are not really intended to have arbitrary dimension, so
|
||||||
// don't add specialisations (or a general case) without a decent
|
// don't add specialisations (or a general case) without a decent
|
||||||
// reason.
|
// reason.
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T, typename...>
|
||||||
struct coord_data;
|
struct coord_init;
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
////---------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T, typename ...tags>
|
||||||
struct coord_data<1, T>
|
struct coord_init<1,T,tags...> : public coord_base<1,T,tags...>
|
||||||
{
|
{
|
||||||
coord_data () = default;
|
coord_init () = default;
|
||||||
coord_data (T v0):
|
coord_init (T v0):
|
||||||
data { v0 }
|
coord_base<1,T,tags...> ({v0})
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
union {
|
|
||||||
T data[1];
|
|
||||||
T x;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
////---------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T, typename ...tags>
|
||||||
struct coord_data<2,T>
|
struct coord_init<2,T,tags...> : public coord_base<2,T,tags...>
|
||||||
{
|
{
|
||||||
coord_data () = default;
|
coord_init () = default;
|
||||||
coord_data (T v0, T v1):
|
coord_init (T v0, T v1):
|
||||||
data { v0, v1 }
|
coord_base<2,T,tags...> ({ v0, v1 })
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
union {
|
|
||||||
T data[2];
|
|
||||||
|
|
||||||
struct { T x, y; };
|
|
||||||
struct { T s, t; };
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
////---------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T, typename ...tags>
|
||||||
struct coord_data<3,T>
|
struct coord_init<3,T,tags...> : public coord_base<3,T,tags...>
|
||||||
{
|
{
|
||||||
coord_data () = default;
|
coord_init () = default;
|
||||||
coord_data (T v0, T v1, T v2):
|
coord_init (T v0, T v1, T v2):
|
||||||
data { v0, v1, v2 }
|
coord_base<3,T,tags...> ({v0, v1, v2})
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
union {
|
|
||||||
T data[3];
|
|
||||||
|
|
||||||
struct { T x, y, z; };
|
|
||||||
struct { T s, t, p; };
|
|
||||||
struct { T r, g, b; };
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
////---------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T, typename ...tags>
|
||||||
struct coord_data<4,T>
|
struct coord_init<4,T,tags...> : public coord_base<4,T,tags...>
|
||||||
{
|
{
|
||||||
coord_data () = default;
|
coord_init () = default;
|
||||||
coord_data (T v0, T v1, T v2, T v3):
|
coord_init (T v0, T v1, T v2, T v3):
|
||||||
data { v0, v1, v2, v3 }
|
coord_base<4,T,tags...> ({ v0, v1, v2, v3 })
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
union {
|
|
||||||
T data[4];
|
|
||||||
|
|
||||||
struct { T x, y, z, w; };
|
|
||||||
struct { T s, t, p, q; };
|
|
||||||
struct { T r, g, b, a; };
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
////---------------------------------------------------------------------
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T, typename ...tags>
|
||||||
struct coord : public coord_data<S,T> {
|
struct coord : public coord_init<S,T,tags...> {
|
||||||
static_assert (S > 0, "coord dimensions must be strictly positive");
|
static_assert (S > 0, "coord dimensions must be strictly positive");
|
||||||
|
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
static constexpr size_t dimension = S;
|
static constexpr size_t dimension = S;
|
||||||
static constexpr size_t elements = S;
|
static constexpr size_t elements = S;
|
||||||
|
|
||||||
using coord_data<S,T>::coord_data;
|
using coord_init<S,T,tags...>::coord_init;
|
||||||
coord () = default;
|
coord () = default;
|
||||||
|
|
||||||
explicit coord (T v)
|
explicit coord (T v)
|
||||||
{ std::fill (std::begin (this->data), std::end (this->data), v); }
|
{ std::fill (std::begin (this->data), std::end (this->data), v); }
|
||||||
|
|
||||||
coord (const coord<S,T> &rhs) = default;
|
coord (const coord<S,T,tags...> &rhs) = default;
|
||||||
coord& operator= (const coord<S,T> &rhs) = default;
|
coord& operator= (const coord<S,T,tags...> &rhs) = default;
|
||||||
|
|
||||||
T& operator[] (size_t i) { return this->data[i]; }
|
T& operator[] (size_t i) { return this->data[i]; }
|
||||||
T operator[] (size_t i) const { return this->data[i]; }
|
T operator[] (size_t i) const { return this->data[i]; }
|
||||||
@ -148,12 +226,12 @@ namespace util {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
////---------------------------------------------------------------------
|
||||||
// XXX: Unsure whether this should really be defined for arbitrary
|
// XXX: Unsure whether this should really be defined for arbitrary
|
||||||
// types in a semantic sense, but practicality suggestes this is the
|
// types in a semantic sense, but practicality suggestes this is the
|
||||||
// best option; point/vector dot product is too useful.
|
// best option; point/vector dot product is too useful.
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T, typename ...tag_a, typename ...tag_b>
|
||||||
T dot (const coord<S,T> &a, const coord<S,T> &b)
|
T dot (const coord<S,T,tag_a...> &a, const coord<S,T,tag_b...> &b)
|
||||||
{
|
{
|
||||||
return std::inner_product (std::begin (a.data),
|
return std::inner_product (std::begin (a.data),
|
||||||
std::end (a.data),
|
std::end (a.data),
|
||||||
|
@ -31,8 +31,8 @@
|
|||||||
namespace util {
|
namespace util {
|
||||||
/// An n-dimensional position in space.
|
/// An n-dimensional position in space.
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
struct point : public detail::coord<S,T> {
|
struct point : public detail::coord<S,T,detail::xyzw> {
|
||||||
using detail::coord<S,T>::coord;
|
using detail::coord<S,T,detail::xyzw>::coord;
|
||||||
|
|
||||||
// point operators
|
// point operators
|
||||||
template <typename U> typename std::common_type<T,U>::type distance (const point<S,U> &) const;
|
template <typename U> typename std::common_type<T,U>::type distance (const point<S,U> &) const;
|
||||||
|
@ -5,10 +5,7 @@
|
|||||||
int
|
int
|
||||||
main (int, char**)
|
main (int, char**)
|
||||||
{
|
{
|
||||||
CHECK_EQ (&util::colour4f::WHITE.x,
|
// Simple check for symbol visibility
|
||||||
&util::colour4f::WHITE.r);
|
|
||||||
|
|
||||||
CHECK_EQ (util::colour4f::WHITE.x, 1.f);
|
|
||||||
CHECK_EQ (util::colour4f::WHITE.r, 1.f);
|
CHECK_EQ (util::colour4f::WHITE.r, 1.f);
|
||||||
CHECK_EQ (util::colour4f::WHITE.g, 1.f);
|
CHECK_EQ (util::colour4f::WHITE.g, 1.f);
|
||||||
CHECK_EQ (util::colour4f::WHITE.b, 1.f);
|
CHECK_EQ (util::colour4f::WHITE.b, 1.f);
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
struct vector : public detail::coord<S, T> {
|
struct vector : public detail::coord<S,T,detail::xyzw,detail::stpq> {
|
||||||
using detail::coord<S,T>::coord;
|
using detail::coord<S,T,detail::xyzw,detail::stpq>::coord;
|
||||||
|
|
||||||
// arithmetic operators
|
// arithmetic operators
|
||||||
vector<S,T> operator* (T) const;
|
vector<S,T> operator* (T) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user