vsg 1.1.3
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 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 bvec3 = t_vec3<int8_t>; // signed 8 bit integer 3D vector
150 using svec3 = t_vec3<int16_t>; // signed 16 bit integer 3D vector
151 using ivec3 = t_vec3<int32_t>; // signed 32 bit integer 3D vector
152 using ubvec3 = t_vec3<uint8_t>; // unsigned 8 bit integer 3D vector
153 using usvec3 = t_vec3<uint16_t>; // unsigned 16 bit integer 3D vector
154 using uivec3 = t_vec3<uint32_t>; // unsigned 32 bit integer 3D vector
155
156 VSG_type_name(vsg::vec3);
157 VSG_type_name(vsg::dvec3);
158 VSG_type_name(vsg::bvec3);
159 VSG_type_name(vsg::svec3);
160 VSG_type_name(vsg::ivec3);
161 VSG_type_name(vsg::ubvec3);
162 VSG_type_name(vsg::usvec3);
163 VSG_type_name(vsg::uivec3);
164
165 template<typename T>
166 constexpr bool operator==(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
167 {
168 return lhs[0] == rhs[0] && lhs[1] == rhs[1] && lhs[2] == rhs[2];
169 }
170
171 template<typename T>
172 constexpr bool operator!=(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
173 {
174 return lhs[0] != rhs[0] || lhs[1] != rhs[1] || lhs[2] != rhs[2];
175 }
176
177 template<typename T>
178 constexpr bool operator<(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
179 {
180 if (lhs[0] < rhs[0]) return true;
181 if (lhs[0] > rhs[0]) return false;
182 if (lhs[1] < rhs[1]) return true;
183 if (lhs[1] > rhs[1]) return false;
184 return lhs[2] < rhs[2];
185 }
186
187 template<typename T>
188 constexpr t_vec3<T> operator-(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
189 {
190 return t_vec3<T>(lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]);
191 }
192
193 template<typename T>
194 constexpr t_vec3<T> operator-(const t_vec3<T>& v)
195 {
196 return t_vec3<T>(-v[0], -v[1], -v[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>& lhs, T rhs)
207 {
208 return t_vec3<T>(lhs[0] * rhs, lhs[1] * rhs, lhs[2] * rhs);
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, T rhs)
219 {
220 if constexpr (std::is_floating_point_v<T>)
221 {
222 T inv = static_cast<T>(1.0) / rhs;
223 return t_vec3<T>(lhs[0] * inv, lhs[1] * inv, lhs[2] * inv);
224 }
225 else
226 {
227 return t_vec3<T>(lhs[0] / rhs, lhs[1] / rhs, lhs[2] / rhs);
228 }
229 }
230
231 template<typename T>
232 constexpr T length(const t_vec3<T>& v)
233 {
234 return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
235 }
236
237 template<typename T>
238 constexpr T length2(const t_vec3<T>& v)
239 {
240 return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
241 }
242
243 template<typename T>
244 constexpr t_vec3<T> normalize(const t_vec3<T>& v)
245 {
246 return v / length(v);
247 }
248
249 template<typename T>
250 constexpr T dot(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
251 {
252 return lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2];
253 }
254
255 template<typename T>
256 constexpr t_vec3<T> cross(const t_vec3<T>& lhs, const t_vec3<T>& rhs)
257 {
258 return t_vec3<T>(lhs[1] * rhs[2] - rhs[1] * lhs[2],
259 lhs[2] * rhs[0] - rhs[2] * lhs[0],
260 lhs[0] * rhs[1] - rhs[0] * lhs[1]);
261 }
262
263 template<typename T>
264 constexpr t_vec3<T> mix(const t_vec3<T>& start, const t_vec3<T>& end, T r)
265 {
266 T one_minus_r = 1 - r;
267 return t_vec3<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 }
271
272 template<typename T>
273 constexpr t_vec3<T> orthogonal(const t_vec3<T>& v)
274 {
275 // use the cross product against the axis which is the most orthogonal to the input vector.
276 auto abs_x = fabs(v.x);
277 auto abs_y = fabs(v.y);
278 auto abs_z = fabs(v.z);
279 if (abs_x < abs_y)
280 {
281 if (abs_x < abs_z) return {0.0, v.z, -v.y}; // v.x shortest, use cross with x axis
282 }
283 else if (abs_y < abs_z)
284 {
285 return {-v.z, 0.0, v.x}; // v.y shortest, use cross with y axis
286 }
287 return {v.y, -v.x, 0.0}; // v.z shortest, use cross with z axis
288 }
289
290} // namespace vsg
291
292#if defined(__clang__)
293# pragma clang diagnostic pop
294#endif
295#if defined(__GNUC__)
296# pragma GCC diagnostic pop
297#endif
t_vec2 template class that represents a 2D vector
Definition vec2.h:38
t_vec3 template class that represents a 3D vector
Definition vec3.h:34