Midnight Graphics
Create Fast and Simple Graphics in C++
Vector.hpp
1 #pragma once
2 
3 #include <Def.hpp>
4 
5 #include <array>
6 #include <initializer_list>
7 
8 namespace mn::Math
9 {
10  template<std::size_t C, typename T>
11  struct Vec
12  {
13  inline constexpr static std::size_t Size = C;
14 
15  T c[C];
16 
17  Vec()
18  {
19  std::memset(c, 0, sizeof(c));
20  }
21 
22  Vec(const std::array<T, C>& vals)
23  {
24  std::uninitialized_copy(vals.begin(), vals.end(), &c[0]);
25  }
26 
27  template<typename A>
28  operator Vec<C, A>() const
29  {
30  Vec<C, A> r;
31  for (uint32_t i = 0; i < C; i++)
32  r.c[i] = static_cast<A>(c[i]);
33  return r;
34  }
35 
36  template<typename A>
37  Vec(std::initializer_list<A> v)
38  {
39  MIDNIGHT_ASSERT(v.size() == C, "Size mismatch");
40  for (uint32_t i = 0; i < C; i++)
41  c[i] = static_cast<T>(*(v.begin() + i));
42  }
43 
44  template<typename A>
45  auto operator+(const Vec<C, A>& vec) const
46  {
47  Vec<C, T> r;
48  for (uint32_t i = 0; i < C; i++)
49  r.c[i] = c[i] + vec.c[i];
50  return r;
51  }
52 
53  template<typename A>
54  auto operator-(const Vec<C, A>& vec) const
55  {
56  Vec<C, T> r;
57  for (uint32_t i = 0; i < C; i++)
58  r.c[i] = c[i] - vec.c[i];
59  return r;
60  }
61 
62  template<typename A>
63  auto operator*(const A& sc) const
64  {
65  Vec<C, T> r;
66  for (uint32_t i = 0; i < C; i++)
67  r.c[i] = c[i] * sc;
68  return r;
69  }
70 
71  template<typename A>
72  auto operator/(const A& sc) const
73  {
74  Vec<C, T> r;
75  for (uint32_t i = 0; i < C; i++)
76  r.c[i] = c[i] / sc;
77  return r;
78  }
79 
80  template<typename A>
81  void operator+=(const Vec<C, A>& vec)
82  {
83  for (uint32_t i = 0; i < C; i++)
84  c[i] += vec.c[i];
85  }
86 
87  template<typename A>
88  void operator-=(const Vec<C, A>& vec)
89  {
90  for (uint32_t i = 0; i < C; i++)
91  c[i] -= vec.c[i];
92  }
93 
94  template<typename A>
95  void operator=(const Vec<C, A>& vec)
96  {
97  for (uint32_t i = 0; i < C; i++)
98  c[i] = static_cast<T>(vec.c[i]);
99  }
100 
101  bool operator==(const Vec<C, T>& vec) const
102  {
103  for (uint32_t i = 0; i < C; i++)
104  if (c[i] != vec.c[i])
105  return false;
106  return true;
107  }
108  };
109 
110  template<std::size_t C, typename T>
111  static Vec<C, T> min(const Vec<C, T>& v1, const Vec<C, T>& v2)
112  {
113  Vec<C, T> ret;
114  for (int i = 0; i < C; i++)
115  ret.c[i] = std::min(v1.c[i], v2.c[i]);
116  return ret;
117  }
118 
119  template<std::size_t C, typename T>
120  static Vec<C, T> max(const Vec<C, T>& v1, const Vec<C, T>& v2)
121  {
122  Vec<C, T> ret;
123  for (int i = 0; i < C; i++)
124  ret.c[i] = std::max(v1.c[i], v2.c[i]);
125  return ret;
126  }
127 
128  template<std::size_t C, typename T,
129  typename = std::enable_if_t<C >= 3>>
130  static Vec<3, T> xyz(const Vec<C, T>& vec)
131  {
132  Vec<3, T> ret;
133  for (int i = 0; i < 3; i++)
134  ret.c[i] = vec.c[i];
135  return ret;
136  }
137 
138  template<std::size_t C, typename T>
139  static T& x(Vec<C, T>& vec)
140  {
141  static_assert(C >= 1);
142  return vec.c[0];
143  }
144 
145  template<std::size_t C, typename T>
146  static T& y(Vec<C, T>& vec)
147  {
148  static_assert(C >= 2);
149  return vec.c[1];
150  }
151 
152  template<std::size_t C, typename T>
153  static T& z(Vec<C, T>& vec)
154  {
155  static_assert(C >= 3);
156  return vec.c[2];
157  }
158 
159  template<std::size_t C, typename T>
160  static const T& x(const Vec<C, T>& vec)
161  {
162  static_assert(C >= 1);
163  return vec.c[0];
164  }
165 
166  template<std::size_t C, typename T>
167  static const T& y(const Vec<C, T>& vec)
168  {
169  static_assert(C >= 2);
170  return vec.c[1];
171  }
172 
173  template<std::size_t C, typename T>
174  static const T& z(const Vec<C, T>& vec)
175  {
176  static_assert(C >= 3);
177  return vec.c[2];
178  }
179 
180  template<std::size_t C, typename T>
181  static T& w(Vec<C, T>& vec)
182  {
183  static_assert(C >= 4);
184  return vec.c[3];
185  }
186 
187  template<std::size_t C, typename T>
188  static const T& w(const Vec<C, T>& vec)
189  {
190  static_assert(C >= 4);
191  return vec.c[3];
192  }
193 
194  template<std::size_t C, typename T1, typename T2>
195  static T1 inner(const Vec<C, T1>& vec1, const Vec<C, T2>& vec2)
196  {
197  T1 t{0};
198  for (uint32_t i = 0; i < C; i++)
199  t += vec1.c[i] * vec2.c[i];
200  return t;
201  }
202 
203  template<std::size_t C, typename T>
204  static double length(const Vec<C, T>& vec)
205  {
206  return sqrt( inner(vec, vec) );
207  }
208 
209  template<std::size_t C, typename T>
210  static Vec<C, T> normalized(const Vec<C, T>& v)
211  {
212  return v / length(v);
213  }
214 
215  template<std::size_t C, typename T>
216  static Vec<C, T> reflect(const Vec<C, T>& incident, const Vec<C, T>& normal)
217  {
218  return incident - normal * static_cast<T>(2.0) * inner(incident, normal);
219  }
220 
221  // Technically the outer product is defined for all dimensions and the cross-product
222  // is restricted to only 3 dimensions... but I'll leave it for posterity's sake
223  template<typename T>
224  static Vec<3, T> outer(const Vec<3, T>& vec1, const Vec<3, T>& vec2)
225  {
226  return Vec<3, T>({
227  y(vec1) * z(vec2) - z(vec1) * y(vec2),
228  z(vec1) * x(vec2) - x(vec1) * z(vec2),
229  x(vec1) * y(vec2) - y(vec1) * x(vec2)
230  });
231  }
232 
233  template<typename T>
234  using Vec2 = Vec<2, T>;
235  using Vec2f = Vec2<r32>;
236  using Vec2u = Vec2<u32>;
237  using Vec2i = Vec2<i32>;
238 
239  template<typename T>
240  using Vec3 = Vec<3, T>;
241  using Vec3f = Vec3<r32>;
242  using Vec3u = Vec3<u32>;
243  using Vec3i = Vec3<i32>;
244 
245  template<typename T>
246  using Vec4 = Vec<4, T>;
247  using Vec4f = Vec4<r32>;
248 }
Definition: Vector.hpp:12