Gamedev Framework (gf)  0.14.0
A C++14 framework for 2D games
Vector.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2019 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 #ifndef GF_VECTOR_H
22 #define GF_VECTOR_H
23 
24 #include <cstddef>
25 #include <cstdint>
26 
27 #include <algorithm>
28 #include <initializer_list>
29 #include <type_traits>
30 
31 #include "Portability.h"
32 #include "Types.h"
33 
34 namespace gf {
35 #ifndef DOXYGEN_SHOULD_SKIP_THIS
36 inline namespace v1 {
37 #endif
38 
60  template<typename T, std::size_t N>
61  struct Vector {
62  #ifndef DOXYGEN_SHOULD_SKIP_THIS
63  static_assert(N > 0, "N must be strictly positive");
64  #endif
65 
72  Vector() = default;
73 
77  constexpr Vector(ZeroType) noexcept
78  {
79  zero();
80  }
81 
95  explicit Vector(T val) noexcept
96  {
97  std::fill_n(data, N, val);
98  }
99 
113  explicit Vector(const T *array)
114  {
115  std::copy_n(array, N, data);
116  }
117 
131  Vector(std::initializer_list<T> list) noexcept
132  {
133  std::copy_n(list.begin(), std::min(list.size(), N), data);
134  }
135 
144  Vector(const Vector& other) = default;
145 
146 
152  template<typename U>
153  Vector(const Vector<U, N>& other) noexcept
154  {
155  static_assert(std::is_convertible<U,T>::value, "Non-convertible types");
156  std::transform(data, data + N, other.data, [](U val) { return static_cast<T>(val); });
157  }
158 
165  Vector& operator=(const Vector& other) = default;
166 
178  constexpr T operator[](std::size_t i) const {
179  return data[i];
180  }
181 
193  constexpr T& operator[](std::size_t i) {
194  return data[i];
195  }
196 
197 
203  T *begin() {
204  return &data[0];
205  }
206 
212  T *end() {
213  return &data[N];
214  }
215 
221  const T *begin() const {
222  return &data[0];
223  }
224 
231  const T *end() const {
232  return &data[N];
233  }
234 
240  const T *cbegin() const {
241  return &data[0];
242  }
243 
250  const T *cend() const {
251  return &data[N];
252  }
253 
257  constexpr void zero() noexcept {
258  for (std::size_t i = 0; i < N; ++i) {
259  data[i] = T{};
260  }
261  }
262 
270  T data[N];
271  };
272 
315  template <typename T>
316  struct Vector<T, 2> {
323  Vector() = default;
324 
328  constexpr Vector(ZeroType) noexcept
329  : x(T(0))
330  , y(T(0))
331  {
332  }
333 
347  explicit constexpr Vector(T val) noexcept
348  : x(val)
349  , y(val)
350  {
351  }
352 
366  explicit constexpr Vector(const T *array)
367  : x(array[0])
368  , y(array[1])
369  {
370  }
371 
378  constexpr Vector(T first, T second) noexcept
379  : x(first)
380  , y(second)
381  {
382  }
383 
392  Vector(const Vector& other) = default;
393 
394 
400  template<typename U>
401  Vector(const Vector<U, 2>& other) noexcept
402  : x(static_cast<T>(other.x))
403  , y(static_cast<T>(other.y))
404  {
405  static_assert(std::is_convertible<U,T>::value, "Non-convertible types");
406  }
407 
419  constexpr T operator[](std::size_t i) const {
420  const T *data[] = { &x, &y };
421  return *data[i];
422  }
423 
435  constexpr T& operator[](std::size_t i) {
436  T *data[] = { &x, &y };
437  return *data[i];
438  }
439 
440 
446  T *begin() {
447  return &x;
448  }
449 
455  T *end() {
456  return &x + 2;
457  }
458 
464  const T *begin() const {
465  return &x;
466  }
467 
474  const T *end() const {
475  return &x + 2;
476  }
482  const T *cbegin() const {
483  return &x;
484  }
485 
492  const T *cend() const {
493  return &x + 2;
494  }
495 
499  constexpr void zero() noexcept {
500  x = y = T{};
501  }
502 
506  union {
507  T x;
508  T u;
509  T s;
511  T col;
512  };
513 
517  union {
518  T y;
519  T v;
520  T t;
522  T row;
523  };
524  };
525 
562  template <typename T>
563  struct Vector<T, 3> {
570  Vector() = default;
571 
575  constexpr Vector(ZeroType) noexcept
576  {
577  zero();
578  }
579 
593  explicit constexpr Vector(T val) noexcept
594  : x(val)
595  , y(val)
596  , z(val)
597  {
598  }
599 
613  explicit constexpr Vector(const T *array)
614  : x(array[0])
615  , y(array[1])
616  , z(array[2])
617  {
618  }
619 
627  constexpr Vector(T first, T second, T third) noexcept
628  : x(first)
629  , y(second)
630  , z(third)
631  {
632  }
633 
640  constexpr Vector(Vector<T, 2> xy, T third)
641  : x(xy.x)
642  , y(xy.y)
643  , z(third)
644  {
645  }
646 
655  Vector(const Vector& other) = default;
656 
657 
663  template<typename U>
664  Vector(const Vector<U, 3>& other) noexcept
665  : x(static_cast<T>(other.x))
666  , y(static_cast<T>(other.y))
667  , z(static_cast<T>(other.z))
668  {
669  static_assert(std::is_convertible<U,T>::value, "Non-convertible types");
670  }
671 
683  constexpr T operator[](std::size_t i) const {
684  const T *data[] = { &x, &y, &z };
685  return *data[i];
686  }
687 
699  constexpr T& operator[](std::size_t i) {
700  T *data[] = { &x, &y, &z };
701  return *data[i];
702  }
703 
704 
710  T *begin() {
711  return &x;
712  }
713 
719  T *end() {
720  return &x + 3;
721  }
722 
728  const T *begin() const {
729  return &x;
730  }
731 
738  const T *end() const {
739  return &x + 3;
740  }
741 
747  const T *cbegin() const {
748  return &x;
749  }
750 
757  const T *cend() const {
758  return &x + 3;
759  }
760 
764  constexpr void zero() noexcept {
765  x = y = z = T{};
766  }
767 
771  constexpr Vector<T, 2> xy() const {
772  return { x, y };
773  }
774 
775 
779  union {
780  T x;
781  T r;
782  };
783 
787  union {
788  T y;
789  T g;
790  };
791 
795  union {
796  T z;
797  T b;
798  };
799  };
800 
837  template <typename T>
838  struct Vector<T, 4> {
845  Vector() = default;
846 
850  constexpr Vector(ZeroType) noexcept
851  {
852  zero();
853  }
854 
868  explicit constexpr Vector(T val) noexcept
869  : x(val)
870  , y(val)
871  , z(val)
872  , w(val)
873  {
874  }
875 
889  explicit constexpr Vector(const T *array)
890  : x(array[0])
891  , y(array[1])
892  , z(array[2])
893  , w(array[3])
894  {
895  }
896 
905  constexpr Vector(T first, T second, T third, T fourth) noexcept
906  : x(first)
907  , y(second)
908  , z(third)
909  , w(fourth)
910  {
911  }
912 
921  Vector(const Vector& other) = default;
922 
923 
929  template<typename U>
930  Vector(const Vector<U, 4>& other) noexcept
931  : x(static_cast<T>(other.x))
932  , y(static_cast<T>(other.y))
933  , z(static_cast<T>(other.z))
934  , w(static_cast<T>(other.w))
935  {
936  static_assert(std::is_convertible<U,T>::value, "Non-convertible types");
937  }
938 
950  constexpr T operator[](std::size_t i) const {
951  const T *data[] = { &x, &y, &z, &w };
952  return *data[i];
953  }
954 
966  constexpr T& operator[](std::size_t i) {
967  T *data[] = { &x, &y, &z, &w };
968  return *data[i];
969  }
970 
971 
977  T *begin() {
978  return &x;
979  }
980 
986  T *end() {
987  return &x + 4;
988  }
989 
995  const T *begin() const {
996  return &x;
997  }
998 
1005  const T *end() const {
1006  return &x + 4;
1007  }
1008 
1014  const T *cbegin() const {
1015  return &x;
1016  }
1017 
1024  const T *cend() const {
1025  return &x + 4;
1026  }
1027 
1031  constexpr void zero() noexcept {
1032  x = y = z = w = T{};
1033  }
1034 
1038  constexpr Vector<T, 2> xy() const {
1039  return { x, y };
1040  }
1041 
1045  constexpr Vector<T, 3> xyz() const {
1046  return { x, y, z };
1047  }
1048 
1052  constexpr Vector<T, 3> rgb() const {
1053  return { r, g, b };
1054  }
1055 
1056 
1060  union {
1061  T x;
1062  T r;
1063  };
1064 
1068  union {
1069  T y;
1070  T g;
1071  };
1072 
1076  union {
1077  T z;
1078  T b;
1079  };
1080 
1084  union {
1085  T w;
1086  T a;
1087  };
1088  };
1089 
1097 
1105 
1113 
1121 
1129 
1137 
1145 
1153 
1161 
1169 
1177 
1185 
1193 
1201 
1209 
1217 
1225 
1233 
1240  template<typename T>
1242 
1249  template<typename T>
1251 
1259 
1267 
1275 
1283 
1291 
1299 
1300 
1301 
1302 // MSVC does not like extern template
1303 #ifndef _MSC_VER
1304  extern template struct GF_API Vector<float, 2>;
1305  extern template struct GF_API Vector<float, 3>;
1306  extern template struct GF_API Vector<float, 4>;
1307 
1308  extern template struct GF_API Vector<double, 2>;
1309  extern template struct GF_API Vector<double, 3>;
1310  extern template struct GF_API Vector<double, 4>;
1311 
1312  extern template struct GF_API Vector<int, 2>;
1313  extern template struct GF_API Vector<int, 3>;
1314  extern template struct GF_API Vector<int, 4>;
1315 
1316  extern template struct GF_API Vector<unsigned, 2>;
1317  extern template struct GF_API Vector<unsigned, 3>;
1318  extern template struct GF_API Vector<unsigned, 4>;
1319 
1320  extern template struct GF_API Vector<bool, 2>;
1321  extern template struct GF_API Vector<bool, 3>;
1322  extern template struct GF_API Vector<bool, 4>;
1323 
1324  extern template struct GF_API Vector<uint8_t, 3>;
1325  extern template struct GF_API Vector<uint8_t, 4>;
1326 #endif
1327 
1345  template<typename T, std::size_t N>
1347 
1354  template<typename T>
1356 
1363  template<typename T>
1365 
1366 
1371  template<typename T, std::size_t N>
1372  inline
1373  void swap(Vector<T,N>& lhs, Vector<T,N>& rhs) noexcept {
1374  std::swap_ranges(lhs.begin(), lhs.end(), rhs.begin());
1375  }
1376 
1384  template<typename ... Types>
1385  constexpr
1386  auto vec(Types... values) -> Vector<std::common_type_t<Types...>, sizeof...(Types)> {
1387  static_assert(sizeof...(Types) > 0, "Vectors must have at least one coordinate");
1388  return { static_cast<std::common_type_t<Types...>>(values)... };
1389  }
1390 
1391 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1392 }
1393 #endif
1394 }
1395 
1396 #endif // GAME_VECTOR_H
constexpr Vector(T first, T second, T third) noexcept
Constructor that takes 3 components.
Definition: Vector.h:627
T x
First coordinate in the (x,y) representation.
Definition: Vector.h:507
T g
Second coordinate in the (r,g,b) representation.
Definition: Vector.h:789
constexpr Vector< T, 3 > xyz() const
Swizzle to get the first three coordinates as a 3D vector.
Definition: Vector.h:1045
const T * cbegin() const
Iterator.on the first element (const version).
Definition: Vector.h:1014
const T * cend() const
Iterator on the element after the last one (const version).
Definition: Vector.h:1024
constexpr Vector(ZeroType) noexcept
Constructor that zero the vector out.
Definition: Vector.h:575
Vector(const Vector< U, 3 > &other) noexcept
Converting copy constructor.
Definition: Vector.h:664
constexpr T & operator[](std::size_t i)
Access to the -th coordinate.
Definition: Vector.h:435
constexpr T & operator[](std::size_t i)
Access to the -th coordinate.
Definition: Vector.h:699
const T * end() const
Iterator on the element after the last one (const version).
Definition: Vector.h:738
Distance< T, 2 > Distance2
A distance function for 2D vectors.
Definition: Vector.h:1355
constexpr Vector2f transform(const Matrix3f &mat, Vector2f point)
Apply an affine transformation to a 2D point.
Definition: Transform.h:323
T z
Third coordinate in the (x,y,z,w) representation.
Definition: Vector.h:1077
T * end()
Iterator to the element after the last one.
Definition: Vector.h:212
constexpr T operator[](std::size_t i) const
Access to the -th coordinate.
Definition: Vector.h:178
const T * cend() const
Iterator on the element after the last one (const version).
Definition: Vector.h:757
constexpr Vector(ZeroType) noexcept
Constructor that zero the vector out.
Definition: Vector.h:328
constexpr T operator[](std::size_t i) const
Access to the -th coordinate.
Definition: Vector.h:950
constexpr Vector< T, 2 > xy() const
Swizzle to get the first two coordinates as a 2D vector.
Definition: Vector.h:1038
constexpr Vector(ZeroType) noexcept
Constructor that zero the vector out.
Definition: Vector.h:77
T * begin()
Iterator.to the first element.
Definition: Vector.h:203
T a
Fourth coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1086
T * begin()
Iterator.to the first element.
Definition: Vector.h:710
constexpr T operator[](std::size_t i) const
Access to the -th coordinate.
Definition: Vector.h:419
T v
Second coordinate in the (u,v) representation.
Definition: Vector.h:519
T y
Second coordinate in the (x,y) representation.
Definition: Vector.h:518
T x
First coordinate in the (x,y,z) representation.
Definition: Vector.h:780
const T * begin() const
Iterator.to the first element (const version).
Definition: Vector.h:464
T width
First coordinate in the size representation.
Definition: Vector.h:510
const T * end() const
Iterator on the element after the last one (const version).
Definition: Vector.h:1005
T s
First coordinate in the (s,t) representation.
Definition: Vector.h:509
constexpr Vector(const T *array)
Constructor that takes an array.
Definition: Vector.h:613
Vector(const Vector< U, N > &other) noexcept
Converting copy constructor.
Definition: Vector.h:153
constexpr Vector(ZeroType) noexcept
Constructor that zero the vector out.
Definition: Vector.h:850
T data[N]
The internal representation of the vector.
Definition: Vector.h:270
const T * cend() const
Iterator on the element after the last one (const version).
Definition: Vector.h:492
T height
Second coordinate in the size representation.
Definition: Vector.h:521
T * end()
Iterator to the element after the last one.
Definition: Vector.h:719
constexpr Vector(T val) noexcept
Constructor that fills the vector with a value.
Definition: Vector.h:593
const T * end() const
Iterator on the element after the last one (const version).
Definition: Vector.h:474
constexpr void zero() noexcept
Zero out the vector.
Definition: Vector.h:499
Distance< T, 3 > Distance3
A distance function for 3D vectors.
Definition: Vector.h:1364
The namespace for gf classes.
Definition: Action.h:35
T g
Second coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1070
T x
First coordinate in the (x,y,z,w) representation.
Definition: Vector.h:1061
constexpr Vector(Vector< T, 2 > xy, T third)
Constructor that takes a 2D vector and a z component.
Definition: Vector.h:640
constexpr auto vec(Types... values) -> Vector< std::common_type_t< Types... >, sizeof...(Types)>
Universal vector factory.
Definition: Vector.h:1386
constexpr void zero() noexcept
Zero out the vector.
Definition: Vector.h:1031
A 4D vector.
Definition: Vector.h:838
Vector(const T *array)
Constructor that takes an array.
Definition: Vector.h:113
T r
First coordinate in the (r,g,b) representation.
Definition: Vector.h:781
Vector(T val) noexcept
Constructor that fills the vector with a value.
Definition: Vector.h:95
const T * cend() const
Iterator on the element after the last one (const version).
Definition: Vector.h:250
const T * cbegin() const
Iterator.on the first element (const version).
Definition: Vector.h:482
constexpr Vector(const T *array)
Constructor that takes an array.
Definition: Vector.h:889
constexpr void zero() noexcept
Zero out the vector.
Definition: Vector.h:257
T b
Third coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1078
void swap(Vector< T, N > &lhs, Vector< T, N > &rhs) noexcept
Swap two vectors.
Definition: Vector.h:1373
T col
First coordinate in the indices representation.
Definition: Vector.h:511
const T * cbegin() const
Iterator.on the first element (const version).
Definition: Vector.h:747
const T * begin() const
Iterator.to the first element (const version).
Definition: Vector.h:995
T * end()
Iterator to the element after the last one.
Definition: Vector.h:986
A 2D vector.
Definition: Vector.h:316
T y
Second coordinate in the (x,y,z) representation.
Definition: Vector.h:788
constexpr ArrayRef< T > array(const T *data, std::size_t size)
Create a constant reference to an array.
Definition: ArrayRef.h:203
constexpr Vector(T val) noexcept
Constructor that fills the vector with a value.
Definition: Vector.h:347
const T * end() const
Iterator on the element after the last one (const version).
Definition: Vector.h:231
constexpr void zero() noexcept
Zero out the vector.
Definition: Vector.h:764
T y
Second coordinate in the (x,y,z,w) representation.
Definition: Vector.h:1069
T u
First coordinate in the (u,v) representation.
Definition: Vector.h:508
T b
Third coordinate in the (r,g,b) representation.
Definition: Vector.h:797
constexpr T & operator[](std::size_t i)
Access to the -th coordinate.
Definition: Vector.h:193
constexpr T operator[](std::size_t i) const
Access to the -th coordinate.
Definition: Vector.h:683
constexpr Vector< T, 3 > rgb() const
Swizzle to get the first three coordinates as a RGB color.
Definition: Vector.h:1052
const T * cbegin() const
Iterator.on the first element (const version).
Definition: Vector.h:240
T * begin()
Iterator.to the first element.
Definition: Vector.h:446
A 3D vector.
Definition: Vector.h:563
T r
First coordinate in the (r,g,b,a) representation.
Definition: Vector.h:1062
General purpose math vector.
Definition: Vector.h:61
T w
Fourth coordinate in the (x,y,z,w) representation.
Definition: Vector.h:1085
const T * begin() const
Iterator.to the first element (const version).
Definition: Vector.h:728
T z
Third coordinate in the (x,y,z) representation.
Definition: Vector.h:796
Vector(const Vector< U, 2 > &other) noexcept
Converting copy constructor.
Definition: Vector.h:401
T(*)(Vector< T, N >, Vector< T, N >) Distance
A distance function.
Definition: Vector.h:1346
const T * begin() const
Iterator.to the first element (const version).
Definition: Vector.h:221
Vector(const Vector< U, 4 > &other) noexcept
Converting copy constructor.
Definition: Vector.h:930
constexpr Vector(const T *array)
Constructor that takes an array.
Definition: Vector.h:366
constexpr Vector(T first, T second, T third, T fourth) noexcept
Constructor that takes 4 components.
Definition: Vector.h:905
T t
Second coordinate in the (s,t) representation.
Definition: Vector.h:520
constexpr Vector< T, 2 > xy() const
Swizzle to get the first two coordinates as a 2D vector.
Definition: Vector.h:771
T * begin()
Iterator.to the first element.
Definition: Vector.h:977
T row
Second coordinate in the indices representation.
Definition: Vector.h:522
Vector(std::initializer_list< T > list) noexcept
Constructor that takes an initializer list.
Definition: Vector.h:131
constexpr Vector(T val) noexcept
Constructor that fills the vector with a value.
Definition: Vector.h:868
constexpr T & operator[](std::size_t i)
Access to the -th coordinate.
Definition: Vector.h:966
T * end()
Iterator to the element after the last one.
Definition: Vector.h:455
constexpr Vector(T first, T second) noexcept
Constructor that takes 2 components.
Definition: Vector.h:378
Semantic type to represent "zero".
Definition: Types.h:69