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

vsg 1.1.9 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{0, 0, 0} {}
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 inline t_vec3& operator*=(const t_vec3& rhs)
119 {
120 value[0] *= rhs.value[0];
121 value[1] *= rhs.value[1];
122 value[2] *= rhs.value[2];
123 return *this;
124 }
125
126 inline t_vec3& operator/=(value_type rhs)
127 {
128 if constexpr (std::is_floating_point_v<value_type>)
129 {
130 value_type inv = static_cast<value_type>(1.0) / rhs;
131 value[0] *= inv;
132 value[1] *= inv;
133 value[2] *= inv;
134 }
135 else
136 {
137 value[0] /= rhs;
138 value[1] /= rhs;
139 value[2] /= rhs;
140 }
141 return *this;
142 }
143
144 explicit operator bool() const noexcept { return value[0] != 0.0 || value[1] != 0.0 || value[2] != 0.0; }
145 };
146
147 using vec3 = t_vec3<float>; // float 3D vector
148 using dvec3 = t_vec3<double>; // double 3D vector
149 using ldvec3 = t_vec3<long double>; // long double 3D vector
150 using bvec3 = t_vec3<int8_t>; // signed 8 bit integer 3D vector
151 using svec3 = t_vec3<int16_t>; // signed 16 bit integer 3D vector
152 using ivec3 = t_vec3<int32_t>; // signed 32 bit integer 3D vector
153 using ubvec3 = t_vec3<uint8_t>; // unsigned 8 bit integer 3D vector
154 using usvec3 = t_vec3<uint16_t>; // unsigned 16 bit integer 3D vector
155 using uivec3 = t_vec3<uint32_t>; // unsigned 32 bit integer 3D vector
156
157 VSG_type_name(vsg::vec3);
158 VSG_type_name(vsg::dvec3);
159 VSG_type_name(vsg::ldvec3);
160 VSG_type_name(vsg::bvec3);
161 VSG_type_name(vsg::svec3);
162 VSG_type_name(vsg::ivec3);
163 VSG_type_name(vsg::ubvec3);
164 VSG_type_name(vsg::usvec3);
165 VSG_type_name(vsg::uivec3);
166
167 template<typename T>
168 constexpr bool operator==(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
169 {
170 return lhs[0] == rhs[0] && lhs[1] == rhs[1] && lhs[2] == rhs[2];
171 }
172
173 template<typename T>
174 constexpr bool operator!=(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
175 {
176 return lhs[0] != rhs[0] || lhs[1] != rhs[1] || lhs[2] != rhs[2];
177 }
178
179 template<typename T>
180 constexpr bool operator<(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
181 {
182 if (lhs[0] < rhs[0]) return true;
183 if (lhs[0] > rhs[0]) return false;
184 if (lhs[1] < rhs[1]) return true;
185 if (lhs[1] > rhs[1]) return false;
186 return lhs[2] < rhs[2];
187 }
188
189 template<typename T>
190 constexpr t_vec3<T> operator-(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
191 {
192 return t_vec3<T>(lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]);
193 }
194
195 template<typename T>
196 constexpr t_vec3<T> operator-(const t_vec3<T>& v)
197 {
198 return t_vec3<T>(-v[0], -v[1], -v[2]);
199 }
200
201 template<typename T>
202 constexpr t_vec3<T> operator+(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
203 {
204 return t_vec3<T>(lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2]);
205 }
206
207 template<typename T>
208 constexpr t_vec3<T> operator*(const t_vec3<T>& lhs, T rhs)
209 {
210 return t_vec3<T>(lhs[0] * rhs, lhs[1] * rhs, lhs[2] * rhs);
211 }
212
213 template<typename T>
214 constexpr t_vec3<T> operator*(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
215 {
216 return t_vec3<T>(lhs[0] * rhs[0], lhs[1] * rhs[1], lhs[2] * rhs[2]);
217 }
218
219 template<typename T>
220 constexpr t_vec3<T> operator/(const t_vec3<T>& lhs, T rhs)
221 {
222 if constexpr (std::is_floating_point_v<T>)
223 {
224 T inv = static_cast<T>(1.0) / rhs;
225 return t_vec3<T>(lhs[0] * inv, lhs[1] * inv, lhs[2] * inv);
226 }
227 else
228 {
229 return t_vec3<T>(lhs[0] / rhs, lhs[1] / rhs, lhs[2] / rhs);
230 }
231 }
232
233 template<typename T>
234 constexpr T length(const t_vec3<T>& v)
235 {
236 return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
237 }
238
239 template<typename T>
240 constexpr T length2(const t_vec3<T>& v)
241 {
242 return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
243 }
244
245 template<typename T>
246 constexpr t_vec3<T> normalize(const t_vec3<T>& v)
247 {
248 return v / length(v);
249 }
250
251 template<typename T>
252 constexpr T dot(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
253 {
254 return lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2];
255 }
256
257 template<typename T>
258 constexpr t_vec3<T> cross(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
259 {
260 return t_vec3<T>(lhs[1] * rhs[2] - rhs[1] * lhs[2],
261 lhs[2] * rhs[0] - rhs[2] * lhs[0],
262 lhs[0] * rhs[1] - rhs[0] * lhs[1]);
263 }
264
265 template<typename T>
266 constexpr t_vec3<T> mix(const t_vec3<T>& start, const t_vec3<T>& end, T r)
267 {
268 T one_minus_r = 1 - r;
269 return t_vec3<T>(start[0] * one_minus_r + end[0] * r,
270 start[1] * one_minus_r + end[1] * r,
271 start[2] * one_minus_r + end[2] * r);
272 }
273
274 template<typename T>
275 constexpr t_vec3<T> orthogonal(const t_vec3<T>& v)
276 {
277 // use the cross product against the axis which is the most orthogonal to the input vector.
278 auto abs_x = fabs(v.x);
279 auto abs_y = fabs(v.y);
280 auto abs_z = fabs(v.z);
281 if (abs_x < abs_y)
282 {
283 if (abs_x < abs_z) return {0.0, v.z, -v.y}; // v.x shortest, use cross with x axis
284 }
285 else if (abs_y < abs_z)
286 {
287 return {-v.z, 0.0, v.x}; // v.y shortest, use cross with y axis
288 }
289 return {v.y, -v.x, 0.0}; // v.z shortest, use cross with z axis
290 }
291
292} // namespace vsg
293
294#if defined(__clang__)
295# pragma clang diagnostic pop
296#endif
297#if defined(__GNUC__)
298# pragma GCC diagnostic pop
299#endif
vsg::t_vec2
t_vec2 template class that represents a 2D vector
Definition vec2.h:38
vsg::t_vec3
t_vec3 template class that represents a 3D vector
Definition vec3.h:34