vsg: include/vsg/maths/vec3.h Source File

vsg 1.1.13 VulkanSceneGraph library

Loading...
Searching...
No Matches
vec3.h
1#pragma once
2
3/* <editor-fold desc="MIT License">
4
5Copyright(c) 2018 Robert Osfield
6
7Permission 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
9The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
11THE 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 disable 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/vec2.h>
27
28namespace vsg
29{
30
32 template<typename T>
33 struct t_vec3
34 {
35 using value_type = T;
36
37 union
38 {
39 value_type value[3];
40 struct
41 {
42 value_type x, y, z;
43 };
44 struct
45 {
46 value_type r, g, b;
47 };
48 struct
49 {
50 value_type s, t, p;
51 };
52 };
53
54 constexpr t_vec3() :
55 value{} {}
56 constexpr t_vec3(const t_vec3& v) :
57 value{v.x, v.y, v.z} {}
58 constexpr t_vec3& operator=(const t_vec3&) = default;
59 constexpr t_vec3(value_type in_x, value_type in_y, value_type in_z) :
60 value{in_x, in_y, in_z} {}
61
62 template<typename R>
63 constexpr t_vec3(const t_vec2<R>& v, value_type in_z) :
64 value{v.x, v.y, in_z} {}
65
66 template<typename R>
67 constexpr explicit t_vec3(const t_vec3<R>& v) :
68 value{static_cast<T>(v.x), static_cast<T>(v.y), static_cast<T>(v.z)} {}
69
70 constexpr std::size_t size() const { return 3; }
71
72 value_type& operator[](std::size_t i) { return value[i]; }
73 value_type operator[](std::size_t i) const { return value[i]; }
74
75 template<typename R>
76 t_vec3& operator=(const t_vec3<R>& rhs)
77 {
78 value[0] = static_cast<value_type>(rhs[0]);
79 value[1] = static_cast<value_type>(rhs[1]);
80 value[2] = static_cast<value_type>(rhs[2]);
81 return *this;
82 }
83
84 T* data() { return value; }
85 const T* data() const { return value; }
86
87 void set(value_type in_x, value_type in_y, value_type in_z)
88 {
89 x = in_x;
90 y = in_y;
91 z = in_z;
92 }
93
94 inline t_vec3& operator+=(const t_vec3& rhs)
95 {
96 value[0] += rhs.value[0];
97 value[1] += rhs.value[1];
98 value[2] += rhs.value[2];
99 return *this;
100 }
101
102 inline t_vec3& operator-=(const t_vec3& rhs)
103 {
104 value[0] -= rhs.value[0];
105 value[1] -= rhs.value[1];
106 value[2] -= rhs.value[2];
107 return *this;
108 }
109
110 inline t_vec3& operator*=(value_type rhs)
111 {
112 value[0] *= rhs;
113 value[1] *= rhs;
114 value[2] *= rhs;
115 return *this;
116 }
117
118 friend constexpr t_vec3<T> operator*(const t_vec3<T>& lhs, T rhs)
119 {
120 return t_vec3<T>(lhs[0] * rhs, lhs[1] * rhs, lhs[2] * rhs);
121 }
122
123 friend constexpr t_vec3<T> operator*(T lhs, const t_vec3<T>& rhs)
124 {
125 return t_vec3<T>(lhs * rhs[0], lhs * rhs[1], lhs * rhs[2]);
126 }
127
128 inline t_vec3& operator*=(const t_vec3& rhs)
129 {
130 value[0] *= rhs.value[0];
131 value[1] *= rhs.value[1];
132 value[2] *= rhs.value[2];
133 return *this;
134 }
135
136 inline t_vec3& operator/=(value_type rhs)
137 {
138 if constexpr (std::is_floating_point_v<value_type>)
139 {
140 value_type inv = numbers<value_type>::one() / rhs;
141 value[0] *= inv;
142 value[1] *= inv;
143 value[2] *= inv;
144 }
145 else
146 {
147 value[0] /= rhs;
148 value[1] /= rhs;
149 value[2] /= rhs;
150 }
151 return *this;
152 }
153
154 explicit operator bool() const noexcept { return value[0] != numbers<value_type>::zero() || value[1] != numbers<value_type>::zero() || value[2] != numbers<value_type>::zero(); }
155 };
156
157 using vec3 = t_vec3<float>; // float 3D vector
158 using dvec3 = t_vec3<double>; // double 3D vector
159 using ldvec3 = t_vec3<long double>; // long double 3D vector
160 using bvec3 = t_vec3<int8_t>; // signed 8 bit integer 3D vector
161 using svec3 = t_vec3<int16_t>; // signed 16 bit integer 3D vector
162 using ivec3 = t_vec3<int32_t>; // signed 32 bit integer 3D vector
163 using ubvec3 = t_vec3<uint8_t>; // unsigned 8 bit integer 3D vector
164 using usvec3 = t_vec3<uint16_t>; // unsigned 16 bit integer 3D vector
165 using uivec3 = t_vec3<uint32_t>; // unsigned 32 bit integer 3D vector
166
167 VSG_type_name(vsg::vec3);
168 VSG_type_name(vsg::dvec3);
169 VSG_type_name(vsg::ldvec3);
170 VSG_type_name(vsg::bvec3);
171 VSG_type_name(vsg::svec3);
172 VSG_type_name(vsg::ivec3);
173 VSG_type_name(vsg::ubvec3);
174 VSG_type_name(vsg::usvec3);
175 VSG_type_name(vsg::uivec3);
176
177 template<typename T>
178 constexpr bool operator==(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
179 {
180 return lhs[0] == rhs[0] && lhs[1] == rhs[1] && lhs[2] == rhs[2];
181 }
182
183 template<typename T>
184 constexpr bool operator!=(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
185 {
186 return lhs[0] != rhs[0] || lhs[1] != rhs[1] || lhs[2] != rhs[2];
187 }
188
189 template<typename T>
190 constexpr bool operator<(const t_vec3<T>& lhs, const t_vec3<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 return lhs[2] < rhs[2];
197 }
198
199 template<typename T>
200 constexpr t_vec3<T> operator-(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
201 {
202 return t_vec3<T>(lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]);
203 }
204
205 template<typename T>
206 constexpr t_vec3<T> operator-(const t_vec3<T>& v)
207 {
208 return t_vec3<T>(-v[0], -v[1], -v[2]);
209 }
210
211 template<typename T>
212 constexpr t_vec3<T> operator+(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
213 {
214 return t_vec3<T>(lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2]);
215 }
216
217 template<typename T>
218 constexpr t_vec3<T> operator*(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
219 {
220 return t_vec3<T>(lhs[0] * rhs[0], lhs[1] * rhs[1], lhs[2] * rhs[2]);
221 }
222
223 template<typename T>
224 constexpr t_vec3<T> operator/(const t_vec3<T>& lhs, T rhs)
225 {
226 if constexpr (std::is_floating_point_v<T>)
227 {
228 T inv = numbers<T>::one() / rhs;
229 return t_vec3<T>(lhs[0] * inv, lhs[1] * inv, lhs[2] * inv);
230 }
231 else
232 {
233 return t_vec3<T>(lhs[0] / rhs, lhs[1] / rhs, lhs[2] / rhs);
234 }
235 }
236
237 template<typename T>
238 constexpr T length(const t_vec3<T>& v)
239 {
240 return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
241 }
242
243 template<typename T>
244 constexpr T length2(const t_vec3<T>& v)
245 {
246 return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
247 }
248
249 template<typename T>
250 constexpr t_vec3<T> normalize(const t_vec3<T>& v)
251 {
252 return v / length(v);
253 }
254
255 template<typename T>
256 constexpr T dot(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
257 {
258 return lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2];
259 }
260
261 template<typename T>
262 constexpr t_vec3<T> cross(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
263 {
264 return t_vec3<T>(lhs[1] * rhs[2] - rhs[1] * lhs[2],
265 lhs[2] * rhs[0] - rhs[2] * lhs[0],
266 lhs[0] * rhs[1] - rhs[0] * lhs[1]);
267 }
268
269 template<typename T>
270 constexpr t_vec3<T> mix(const t_vec3<T>& start, const t_vec3<T>& end, T r)
271 {
272 T one_minus_r = numbers<T>::one() - r;
273 return t_vec3<T>(start[0] * one_minus_r + end[0] * r,
274 start[1] * one_minus_r + end[1] * r,
275 start[2] * one_minus_r + end[2] * r);
276 }
277
278 template<typename T>
279 constexpr t_vec3<T> orthogonal(const t_vec3<T>& v)
280 {
281 // use the cross product against the axis which is the most orthogonal to the input vector.
282 auto abs_x = fabs(v.x);
283 auto abs_y = fabs(v.y);
284 auto abs_z = fabs(v.z);
285 if (abs_x < abs_y)
286 {
287 if (abs_x < abs_z) return {numbers<T>::zero(), v.z, -v.y}; // v.x shortest, use cross with x axis
288 }
289 else if (abs_y < abs_z)
290 {
291 return {-v.z, numbers<T>::zero(), v.x}; // v.y shortest, use cross with y axis
292 }
293 return {v.y, -v.x, numbers<T>::zero()}; // v.z shortest, use cross with z axis
294 }
295
296} // namespace vsg
297
298#if defined(__clang__)
299# pragma clang diagnostic pop
300#endif
301#if defined(__GNUC__)
302# pragma GCC diagnostic pop
303#endif
vsg::t_vec2
t_vec2 template class that represents a 2D vector
Definition vec2.h:39
vsg::t_vec3
t_vec3 template class that represents a 3D vector
Definition vec3.h:34