Skip to main content

vec3.ixx File

3D vector type and utilities. More...

Included Headers

#include <cassert> #include <cmath> #include <memory> #include <helios.math.utils> #include <helios.math.traits.FloatingPointType> #include <helios.math.concepts> #include <helios.math.types:vec2>

Namespaces Index

namespacehelios
namespacemath

Mathematical operations and types. More...

Classes Index

structvec3<T>

Represents a 3-dimensional vector of the generic type <T>. More...

Description

3D vector type and utilities.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file vec3.ixx
3 * @brief 3D vector type and utilities.
4 */
5module;
6
7#include <cassert>
8#include <cmath>
9#include <memory>
10
11export module helios.math.types:vec3;
12
13import :vec2;
14import helios.math.concepts;
15import helios.math.traits.FloatingPointType;
16import helios.math.utils;
17
18export namespace helios::math {
19
20 template<helios::math::Numeric T>
21 struct vec4;
22
23 /**
24 * @brief Represents a 3-dimensional vector of the generic type <T>.
25 *
26 * The `vec3` struct provides a lightweight and efficient way to handle 3D
27 * vector mathematics for the numeric types float, int, double. For convenient access,
28 * the shorthands `vec3f`, `vec3d` and `vec3i` are available.
29 *
30 * @tparam T The numeric type of the vector components.
31 */
32 template<helios::math::Numeric T>
33 struct vec3 {
34
35 private:
36 /**
37 * @brief Internal array storing the vector components.
38 */
39 T v[3];
40
41 public:
42
43
44 /**
45 * @brief Creates a new vec3 with its values initialized to (0, 0, 0)
46 */
47 constexpr vec3() noexcept : v{static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)} {}
48
49
50 /**
51 * @brief Constructs a new vec3 with the specified x, y, z components.
52 *
53 * @param x The value for the x component.
54 * @param y The value for the y component.
55 * @param z The value for the z component.
56 *
57 */
58 constexpr vec3(const T x, const T y, const T z) noexcept : v{x, y, z} {}
59
60
61 /**
62 * @brief Constructs a new vec3 with the specified value as the x,y,z components.
63 *
64 * @param v The value for the components.
65 *
66 */
67 constexpr explicit vec3(const T v) noexcept : v{v, v, v} {}
68
69 /**
70 * @brief Constructs a new vec3 with x,y components initialized to those of the vec2
71 * and vec3 set to 0
72 *
73 * @param v The vec2 to use for the x,y components.
74 *
75 */
76 constexpr explicit vec3(const helios::math::vec2<T> v) noexcept : v{v[0], v[1], static_cast<T>(0)} {}
77
78 /**
79 * @brief Constructs a new vec3 with x,y components initialized to those of the vec2
80 * and the z component set to the specified value.
81 *
82 * @param v The vec2 to use for the x,y components.
83 * @param f The value for the z component.
84 */
85 constexpr explicit vec3(const helios::math::vec2<T> v, T f) noexcept : v{v[0], v[1], f} {}
86
87 /**
88 * @brief Provides read only access to the vector components.
89 * Bounds checking is performed via `assert` in debug builds.
90 *
91 * @param i The index to query
92 *
93 * @return A const ref to the requested component.
94 */
95 constexpr const T& operator[](const size_t i) const noexcept {
96 assert(i <= 2 && "vec3 - Index out of bounds.");
97 return this->v[i];
98 }
99
100
101 /**
102 * @brief Provides read-write access to the vector components.
103 * Bounds checking is performed via `assert` in debug builds.
104 *
105 * @param i The index to query
106 *
107 * @return A const ref to the requested component.
108 */
109 constexpr T& operator[](const size_t i) noexcept {
110 assert(i <= 2 && "vec3 - Index out of bounds.");
111 return this->v[i];
112 }
113
114
115 /**
116 * @brief Computes the Euclidean norm (magnitude) of this vector and returns it.
117 *
118 * @return The norm (magnitude) of this vector as a value of type FloatingPointType<T>.
119 */
120 FloatingPointType<T> length() const noexcept {
121 return static_cast<FloatingPointType<T>>(std::sqrt(
122 static_cast<double>(this->v[0]) * static_cast<double>(this->v[0]) +
123 static_cast<double>(this->v[1]) * static_cast<double>(this->v[1]) +
124 static_cast<double>(this->v[2]) * static_cast<double>(this->v[2])
125 ));
126 }
127
128 /**
129 * @brief Computes the cross product of this vector and v2.
130 *
131 * @param v2 The second vec3<T> vector.
132 *
133 * @return The cross product as a value of type vec3<T>.
134 */
135 [[nodiscard]] vec3<T> cross(const helios::math::vec3<T>& v2) const noexcept;
136
137 /**
138 * @brief Computes the dot product of this vector and v2.
139 *
140 * @param v2 The second vec3<T> vector.
141 *
142 * @return The dot product as a value of type T.
143 */
144 [[nodiscard]] T dot(const helios::math::vec3<T>& v2) const noexcept;
145
146 /**
147 * @brief Converts this 3D vector to a 4D homogeneous vector.
148 *
149 * @details
150 * Creates a vec4 with the x, y, z components from this vector and sets
151 * the w component to 0, representing a direction in homogeneous coordinates.
152 *
153 * @return A new vec4<T> instance with components (x, y, z, 0).
154 */
155 [[nodiscard]] vec4<T> toVec4() const noexcept;
156
157 /**
158 * @brief Converts this 3D vector to a 2D vector by discarding the z-component.
159 *
160 * @return A new vec2<T> instance with components (x, y).
161 */
162 [[nodiscard]] vec2<T> toVec2() const noexcept;
163
164 /**
165 * @brief Converts this 3D vector to a 4D homogeneous vector.
166 *
167 * @details
168 * Creates a vec4 with the x, y, z components from this vector and sets
169 * the w component accordingly, representing a direction in homogeneous coordinates.
170 *
171 * @param w The value of the w component.
172 *
173 * @return A new vec4<T> instance with components (x, y, z, w).
174 */
175 [[nodiscard]] vec4<T> toVec4(T w) const noexcept;
176
177 /**
178 * @brief Returns a normalized version of this vector.
179 *
180 * @return A new vec3<FloatingPointType<T>> instance representing the normalized vector.
181 */
182 [[nodiscard]] vec3<FloatingPointType<T>> normalize() const noexcept;
183
184 /**
185 * @brief Strictly compares the elements of this vector with the elements
186 * of the rgt vector.
187 *
188 * @param rgt The right vector to compare for equal values.
189 *
190 * @return True if all elements are equal (==), false otherwise.
191 */
192 constexpr bool operator==(const vec3<T>& rgt) const {
193 return v[0] == rgt[0] && v[1] == rgt[1] && v[2] == rgt[2];
194 }
195
196
197 /**
198 * @brief Compares this vector's elements with the rgt vector considering
199 * an epsilon value.
200 * Returns true if for all elements the equation |a-b| <= epsilon
201 * holds.
202 *
203 * @param rgt The other vector to compare with this vector for equality.
204 * @param epsilon The epsilon value to use for comparison. If omitted, the default epsilon (0.0001) is used.
205 *
206 * @return True if the elements of the vectors are considered equal,
207 * otherwise false.
208 *
209 * @see https://realtimecollisiondetection.net/blog/?p=89
210 *
211 * @todo account for abs (values close to zero) and rel
212 * (larger values), move epsilon to global constant?
213 */
214 constexpr bool same(const vec3<T>& rgt, T epsilon = 0.0001) const {
215 return std::fabs(v[0] - rgt[0]) <= epsilon &&
216 std::fabs(v[1] - rgt[1]) <= epsilon &&
217 std::fabs(v[2] - rgt[2]) <= epsilon;
218 }
219
220 /**
221 * @brief Returns a new vector with the y-component negated.
222 *
223 * @return A new vec3<T> with (x, -y, z).
224 */
225 constexpr helios::math::vec3<T> flipY() const noexcept {
226 return helios::math::vec3<T>{v[0], -v[1], v[2]};
227 }
228
229 /**
230 * @brief Returns a new vector with the y-component replaced by the given value.
231 *
232 * @param y The new y value.
233 * @return A new vec3<T> with (x, y, z).
234 */
235 constexpr helios::math::vec3<T> withY(T y) const noexcept {
236 return helios::math::vec3<T>{v[0], y, v[2]};
237 }
238
239 /**
240 * @brief Returns a new vector with the x-component negated.
241 *
242 * @return A new vec3<T> with (-x, y, z).
243 */
244 constexpr helios::math::vec3<T> flipX() const noexcept {
245 return helios::math::vec3<T>{-v[0], v[1], v[2]};
246 }
247
248 /**
249 * @brief Returns a new vector with the x-component replaced by the given value.
250 *
251 * @param x The new x value.
252 * @return A new vec3<T> with (x, y, z).
253 */
254 constexpr helios::math::vec3<T> withX(T x) const noexcept {
255 return helios::math::vec3<T>{x, v[1], v[2]};
256 }
257
258 /**
259 * @brief Checks if this vector is normalized (unit length).
260 *
261 * @details A vector is considered normalized if its squared length
262 * equals 1 within the tolerance defined by EPSILON_LENGTH.
263 *
264 * @return true if the vector is approximately unit length, false otherwise.
265 */
266 constexpr bool isNormalized() const noexcept {
267 const auto lenSquared =
268 static_cast<FloatingPointType<T>>(v[0]) * static_cast<FloatingPointType<T>>(v[0]) +
269 static_cast<FloatingPointType<T>>(v[1]) * static_cast<FloatingPointType<T>>(v[1]) +
270 static_cast<FloatingPointType<T>>(v[2]) * static_cast<FloatingPointType<T>>(v[2]);
271
272 return std::abs(lenSquared - static_cast<FloatingPointType<T>>(1.0)) <= helios::math::EPSILON_LENGTH;
273 }
274 };
275
276
277 /**
278 * @brief Multiplies a 3D vector by a scalar value.
279 *
280 * @tparam T The numeric type of the vector components.
281 * @param v The vec3<T> vector to be multiplied.
282 * @param n The scalar value to multiply the vector by.
283 *
284 * @return a new vec3<T> instance representing the result of the scalar
285 * multiplication.
286 */
287 template<helios::math::Numeric T>
288 constexpr vec3<T> operator*(const vec3<T>& v, const T n) noexcept {
289 return vec3<T>{v[0] * n, v[1] * n, v[2] * n};
290 }
291
292 /**
293 * @brief Divides a 3D vector by a scalar value.
294 *
295 * @tparam T The numeric type of the vector components.
296 * @param v The vec3<T> vector to be divided.
297 * @param s The scalar divisor. Must not be zero.
298 *
299 * @return A new vec3<T> instance representing the result of the scalar division.
300 *
301 * @pre s != 0 (asserted in debug builds).
302 */
303 template<helios::math::Numeric T>
304 constexpr vec3<T> operator/(const vec3<T>& v, T s) noexcept {
305 assert(static_cast<T>(0) != s && "s must not be 0");
306 const T inv = static_cast<T>(1) / s;
307 return vec3<T>{ v[0] * inv, v[1] * inv, v[2] * inv };
308 }
309
310 /**
311 * @brief Multiplies a scalar value by a 3D vector.
312 *
313 * @tparam T The numeric type of the vector components.
314 * @param n The scalar value to multiply the vector by.
315 * @param v The vec3<T> vector to be multiplied.
316 *
317 * @return A new vec3<T> instance representing the result of the scalar
318 * multiplication.
319 */
320 template<helios::math::Numeric T>
321 constexpr vec3<T> operator*(const T n, const vec3<T>& v) noexcept {
322 return vec3<T>{v[0] * n, v[1] * n, v[2] * n};
323 }
324
325 /**
326 * @brief Multiplies two vectors componentwise.
327 *
328 * @tparam T The numeric type of the vector components.
329 * @param v1 The left-hand vec3<T> vector to be multiplied.
330 * @param v2 The right-hand vec3<T> vector to be multiplied.
331 *
332 * @return A new vec3<T> instance representing the result of the componentwise multiplication
333 * of the two vectors.
334 */
335 template<helios::math::Numeric T>
336 constexpr vec3<T> operator*(const vec3<T>& v1, const vec3<T>& v2) noexcept {
337 return vec3<T>{v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]};
338 }
339
340
341 /**
342 * @brief Calculates the componentwise sum of the two vectors.
343 *
344 * @tparam T The numeric type of the vector components.
345 * @param v1 The left-hand vec3<T> vector to be added.
346 * @param v2 The right-hand vec3<T> vector to be added.
347 *
348 * @return A new vec3<T> instance representing the sum of the two vectors.
349 */
350 template<helios::math::Numeric T>
351 constexpr vec3<T> operator+(const vec3<T>& v1, const vec3<T>& v2) noexcept {
352 return vec3<T>{v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]};
353 }
354
355
356 /**
357 * @brief Computes the cross product of two 3D vectors.
358 *
359 * @tparam T The numeric type of the vector components.
360 * @param v1 The first vec3<T> vector.
361 * @param v2 The second vec3<T> vector.
362 *
363 * @return A new vec3<T> instance representing the cross product.
364 */
365 template<helios::math::Numeric T>
366 constexpr vec3<T> cross(const vec3<T>& v1, const vec3<T>& v2) noexcept {
367 return vec3{
368 v1[1]*v2[2] - v1[2]*v2[1],
369 v1[2]*v2[0] - v1[0]*v2[2],
370 v1[0]*v2[1] - v1[1]*v2[0]
371 };
372 }
373
374 /**
375 * @brief Computes the dot product of two 3D vectors.
376 *
377 * @tparam T The numeric type of the vector components.
378 * @param v1 The first vec3<T> vector.
379 * @param v2 The second vec3<T> vector.
380 *
381 * @return The dot product as a value of type T.
382 */
383 template<helios::math::Numeric T>
384 constexpr T dot(const vec3<T>& v1, const vec3<T>& v2) noexcept {
385 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
386 }
387
388
389 /**
390 * @brief Computes the difference between two vectors (vector subtraction).
391 *
392 * @tparam T The numeric type of the vector components.
393 * @param v1 The first vec3<T> vector.
394 * @param v2 The second vec3<T> vector.
395 *
396 * @return A new vec3<T> instance representing the difference between v1 and v2.
397 */
398 template<helios::math::Numeric T>
399 constexpr vec3<T> operator-(const vec3<T>& v1, const vec3<T>& v2) noexcept {
400 return vec3{v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]};
401 }
402
403 template<helios::math::Numeric T>
404 inline vec3<T> vec3<T>::cross(const vec3<T>& v2) const noexcept {
405 return vec3{
406 v[1]*v2[2] - v[2]*v2[1],
407 v[2]*v2[0] - v[0]*v2[2],
408 v[0]*v2[1] - v[1]*v2[0]
409 };
410 }
411
412 template<helios::math::Numeric T>
413 inline vec4<T> vec3<T>::toVec4() const noexcept {
414 return vec4<T>{v[0], v[1], v[2], static_cast<T>(0)};
415 }
416
417 template<helios::math::Numeric T>
418 inline vec2<T> vec3<T>::toVec2() const noexcept {
419 return vec2<T>{v[0], v[1]};
420 }
421
422 template<helios::math::Numeric T>
423 inline vec4<T> vec3<T>::toVec4(T w) const noexcept {
424 return vec4<T>{v[0], v[1], v[2], w};
425 }
426
427 template<helios::math::Numeric T>
428 inline T vec3<T>::dot(const vec3<T>& v2) const noexcept {
429 return v[0]*v2[0] + v[1]*v2[1] + v[2]*v2[2];
430 }
431
432
433 template<helios::math::Numeric T>
435 if (this->length() == static_cast<FloatingPointType<T>>(0)) {
437 static_cast<FloatingPointType<T>>(0),
438 static_cast<FloatingPointType<T>>(0),
439 static_cast<FloatingPointType<T>>(0)
440 );
441 }
442
444 static_cast<FloatingPointType<T>>(v[0]) / this->length(),
445 static_cast<FloatingPointType<T>>(v[1]) / this->length(),
446 static_cast<FloatingPointType<T>>(v[2]) / this->length()
447 );
448 }
449
450 /**
451 * @brief Single-precision floating-point 3D vector.
452 */
454
455 /**
456 * @brief Integer 3D vector.
457 */
459
460 /**
461 * @brief Double-precision floating-point 3D vector.
462 */
464
465 /**
466 * @brief Unit vector along the positive X-axis (1, 0, 0).
467 *
468 * @details Commonly used as the default "right" direction in helios's
469 * left-handed coordinate system.
470 */
471 inline constexpr vec3f X_AXISf{1.0f, 0.0f, 0.0f};
472
473 /**
474 * @brief Unit vector along the positive Y-axis (0, 1, 0).
475 *
476 * @details Commonly used as the default "up" direction in helios's
477 * left-handed coordinate system.
478 */
479 inline constexpr vec3f Y_AXISf{0.0f, 1.0f, 0.0f};
480
481 /**
482 * @brief Unit vector along the positive Z-axis (0, 0, 1).
483 *
484 * @details Commonly used as the default "forward" direction in helios's
485 * left-handed coordinate system.
486 */
487 inline constexpr vec3f Z_AXISf{0.0f, 0.0f, 1.0f};
488
489
490} // namespace helios::math

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.