vsg  1.0.4
VulkanSceneGraph library
vec4.h
1 #pragma once
2 
3 /* <editor-fold desc="MIT License">
4 
5 Copyright(c) 2018 Robert Osfield
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 
9 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 
13 </editor-fold> */
14 
15 // we can't implement the anonymous union/structs combination without causing warnings, so disabled them for just this header
16 #if defined(__GNUC__)
17 # pragma GCC diagnostic push
18 # pragma GCC diagnostic ignored "-Wpedantic"
19 #endif
20 #if defined(__clang__)
21 # pragma clang diagnostic push
22 # pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
23 # pragma clang diagnostic ignored "-Wnested-anon-types"
24 #endif
25 
26 #include <vsg/maths/vec3.h>
27 
28 namespace vsg
29 {
30 
32  template<typename T>
33  struct t_vec4
34  {
35  using value_type = T;
36 
37  union
38  {
39  value_type value[4];
40  struct
41  {
42  value_type x, y, z, w;
43  };
44  struct
45  {
46  value_type r, g, b, a;
47  };
48  struct
49  {
50  value_type s, t, p, q;
51  };
52  t_vec3<T> xyz;
53  };
54 
55  constexpr t_vec4() :
56  value{} {}
57  constexpr t_vec4(const t_vec4& v) :
58  value{v.x, v.y, v.z, v.w} {}
59  constexpr t_vec4& operator=(const t_vec4&) = default;
60 
61  constexpr t_vec4(value_type in_x, value_type in_y, value_type in_z, value_type in_w) :
62  value{in_x, in_y, in_z, in_w} {}
63 
64  template<typename R>
65  constexpr explicit t_vec4(const t_vec4<R>& v) :
66  value{static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z), static_cast<T>(v.w)} {}
67 
68  template<typename R>
69  constexpr t_vec4(const t_vec2<R>& v, value_type in_z, value_type in_w) :
70  value{static_cast<T>(v.x), static_cast<T>(v.y), in_z, in_w} {}
71 
72  template<typename R>
73  constexpr t_vec4(const t_vec3<R>& v, value_type in_w) :
74  value{static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z), in_w} {}
75 
76  constexpr std::size_t size() const { return 4; }
77 
78  value_type& operator[](std::size_t i) { return value[i]; }
79  value_type operator[](std::size_t i) const { return value[i]; }
80 
81  template<typename R>
82  t_vec4& operator=(const t_vec4<R>& rhs)
83  {
84  value[0] = static_cast<value_type>(rhs[0]);
85  value[1] = static_cast<value_type>(rhs[1]);
86  value[2] = static_cast<value_type>(rhs[2]);
87  value[3] = static_cast<value_type>(rhs[3]);
88  return *this;
89  }
90 
91  T* data() { return value; }
92  const T* data() const { return value; }
93 
94  void set(value_type in_x, value_type in_y, value_type in_z, value_type in_w)
95  {
96  x = in_x;
97  y = in_y;
98  z = in_z;
99  w = in_w;
100  }
101 
102  inline t_vec4& operator+=(const t_vec4& rhs)
103  {
104  value[0] += rhs.value[0];
105  value[1] += rhs.value[1];
106  value[2] += rhs.value[2];
107  value[3] += rhs.value[3];
108  return *this;
109  }
110 
111  inline t_vec4& operator-=(const t_vec4& rhs)
112  {
113  value[0] -= rhs.value[0];
114  value[1] -= rhs.value[1];
115  value[2] -= rhs.value[2];
116  value[3] -= rhs.value[3];
117  return *this;
118  }
119 
120  inline t_vec4& operator*=(value_type rhs)
121  {
122  value[0] *= rhs;
123  value[1] *= rhs;
124  value[2] *= rhs;
125  value[3] *= rhs;
126  return *this;
127  }
128 
129  inline t_vec4& operator*=(const t_vec4& rhs)
130  {
131  value[0] *= rhs.value[0];
132  value[1] *= rhs.value[1];
133  value[2] *= rhs.value[2];
134  value[3] *= rhs.value[3];
135  return *this;
136  }
137 
138  inline t_vec4& operator/=(value_type rhs)
139  {
140  if constexpr (std::is_floating_point_v<value_type>)
141  {
142  value_type inv = static_cast<value_type>(1.0) / rhs;
143  value[0] *= inv;
144  value[1] *= inv;
145  value[2] *= inv;
146  value[3] *= inv;
147  }
148  else
149  {
150  value[0] /= rhs;
151  value[1] /= rhs;
152  value[2] /= rhs;
153  value[3] /= rhs;
154  }
155  return *this;
156  }
157  };
158 
159  using vec4 = t_vec4<float>; // float 4D vector
160  using dvec4 = t_vec4<double>; // double 4D vector
161  using bvec4 = t_vec4<std::int8_t>; // signed 8 bit integer 4D vector
162  using svec4 = t_vec4<std::int16_t>; // signed 16 bit integer 4D vector
163  using ivec4 = t_vec4<std::int32_t>; // signed 32 bit integer 4D vector
164  using ubvec4 = t_vec4<std::uint8_t>; // unsigned 8 bit integer 4D vector
165  using usvec4 = t_vec4<std::uint16_t>; // unsigned 16 bit integer 4D vector
166  using uivec4 = t_vec4<std::uint32_t>; // unsigned 32 bit integer 4D vector
167 
168  VSG_type_name(vsg::vec4);
169  VSG_type_name(vsg::dvec4);
170  VSG_type_name(vsg::bvec4);
171  VSG_type_name(vsg::svec4);
172  VSG_type_name(vsg::ivec4);
173  VSG_type_name(vsg::ubvec4);
174  VSG_type_name(vsg::usvec4);
175  VSG_type_name(vsg::uivec4);
176 
177  template<typename T>
178  constexpr bool operator==(const t_vec4<T>& lhs, const t_vec4<T>& rhs)
179  {
180  return lhs[0] == rhs[0] && lhs[1] == rhs[1] && lhs[2] == rhs[2] && lhs[3] == rhs[3];
181  }
182 
183  template<typename T>
184  constexpr bool operator!=(const t_vec4<T>& lhs, const t_vec4<T>& rhs)
185  {
186  return lhs[0] != rhs[0] || lhs[1] != rhs[1] || lhs[2] != rhs[2] || lhs[3] != rhs[3];
187  }
188 
189  template<typename T>
190  constexpr bool operator<(const t_vec4<T>& lhs, const t_vec4<T>& rhs)
191  {
192  if (lhs[0] < rhs[0]) return true;
193  if (lhs[0] > rhs[0]) return false;
194  if (lhs[1] < rhs[1]) return true;
195  if (lhs[1] > rhs[1]) return false;
196  if (lhs[2] < rhs[2]) return true;
197  if (lhs[2] > rhs[2]) return false;
198  return lhs[3] < rhs[3];
199  }
200 
201  template<typename T>
202  constexpr t_vec4<T> operator-(const t_vec4<T>& lhs, const t_vec4<T>& rhs)
203  {
204  return t_vec4<T>(lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2], lhs[3] - rhs[3]);
205  }
206 
207  template<typename T>
208  constexpr t_vec4<T> operator-(const t_vec4<T>& v)
209  {
210  return t_vec4<T>(-v[0], -v[1], -v[2], -v[3]);
211  }
212 
213  template<typename T>
214  constexpr t_vec4<T> operator+(const t_vec4<T>& lhs, const t_vec4<T>& rhs)
215  {
216  return t_vec4<T>(lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2], lhs[3] + rhs[3]);
217  }
218 
219  template<typename T>
220  constexpr t_vec4<T> operator*(const t_vec4<T>& lhs, T rhs)
221  {
222  return t_vec4<T>(lhs[0] * rhs, lhs[1] * rhs, lhs[2] * rhs, lhs[3] * rhs);
223  }
224 
225  template<typename T>
226  constexpr t_vec4<T> operator*(const t_vec4<T>& lhs, const t_vec4<T>& rhs)
227  {
228  return t_vec4<T>(lhs[0] * rhs[0], lhs[1] * rhs[1], lhs[2] * rhs[2], lhs[3] * rhs[3]);
229  }
230 
231  template<typename T>
232  constexpr t_vec4<T> operator/(const t_vec4<T>& lhs, T rhs)
233  {
234  if constexpr (std::is_floating_point_v<T>)
235  {
236  T inv = static_cast<T>(1.0) / rhs;
237  return t_vec4<T>(lhs[0] * inv, lhs[1] * inv, lhs[2] * inv, lhs[3] * inv);
238  }
239  else
240  {
241  return t_vec4<T>(lhs[0] / rhs, lhs[1] / rhs, lhs[2] / rhs, lhs[3] / rhs);
242  }
243  }
244 
245  template<typename T>
246  constexpr T length(const t_vec4<T>& v)
247  {
248  return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);
249  }
250 
251  template<typename T>
252  constexpr T length2(const t_vec4<T>& v)
253  {
254  return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
255  }
256 
257  template<typename T>
258  constexpr t_vec4<T> normalize(const t_vec4<T>& v)
259  {
260  return v / length(v);
261  }
262 
263  template<typename T>
264  constexpr t_vec4<T> mix(const t_vec4<T>& start, const t_vec4<T>& end, T r)
265  {
266  T one_minus_r = 1 - r;
267  return t_vec4<T>(start[0] * one_minus_r + end[0] * r,
268  start[1] * one_minus_r + end[1] * r,
269  start[2] * one_minus_r + end[2] * r,
270  start[3] * one_minus_r + end[3] * r);
271  }
272 
273 } // namespace vsg
274 
275 #if defined(__clang__)
276 # pragma clang diagnostic pop
277 #endif
278 #if defined(__GNUC__)
279 # pragma GCC diagnostic pop
280 #endif
t_vec2 template class that a represents a 2D vector
Definition: vec2.h:36
t_vec3 template class that a represents a 3D vector
Definition: vec3.h:34
t_vec4 template class that a represents a 4D vector
Definition: vec4.h:34