SH4ZAM! 0.9.1
Fast math library for the Sega Dreamcast's SH4 CPU
Loading...
Searching...
No Matches
shz_vector.hpp
Go to the documentation of this file.
1/*! \file
2 * \brief C++ Vector types and operations.
3 * \ingroup vector
4 *
5 * This file provides types and mathematical functions for representing and
6 * operating on vectors within C++.
7 *
8 * \author 2025 Falco Girgis
9 * \copyright MIT License
10 *
11 * \todo
12 * - C++ proxy class equivalent for shz_vecN_deref().
13 * - C++ better swizzling mechanism
14 */
15
16#ifndef SHZ_VECTOR_HPP
17#define SHZ_VECTOR_HPP
18
19#include <compare>
20#include <concepts>
21
22#include "shz_vector.h"
23#include "shz_scalar.hpp"
24#include "shz_trig.hpp"
25
26namespace shz {
27
28struct vec2;
29struct vec3;
30struct vec4;
31
32/*! Common C++ base structure inherited by all vector types.
33
34 This struct template serves as the base class for all
35 concrete vector types, providing:
36 - Common API routines
37 - Adaptor between C and C++ types
38 - Convenience overloaded operators and STL iterators.
39
40 \sa shz::vec2, shz::vec3, shz::vec4
41*/
42template<typename CRTP, typename C, size_t R>
43struct vecN: C {
44 using CppType = CRTP; //!< Cpp derived type
45 using CType = C; //!< C base type
46
47 static constexpr size_t Rows = R; //!< Number of rows
48 static constexpr size_t Cols = 1; //!< Number of columns
49
50 //! Default constructor, does nothing.
51 vecN() noexcept = default;
52
53 //! Default copy constructor.
54 vecN(const vecN& other) noexcept = default;
55
56 //! Converting constructor from existing C instance.
57 SHZ_FORCE_INLINE vecN(const CType& other) noexcept:
58 CType(other) {}
59
60 //! Converting constructor from existing volatile C instance.
61 SHZ_FORCE_INLINE vecN(const volatile CType& other) noexcept:
62 CType(const_cast<const CType&>(other)) {}
63
64 //! Conversion operator for going from a layout-compatible vector type to a SH4ZAM vector type.
65 SHZ_FORCE_INLINE static CppType from(const auto& raw) noexcept {
66 return *reinterpret_cast<const CppType*>(&raw);
67 }
68
69 //! Conversion operator for going from a SH4ZAM vector type to another layout-compatible type.
70 template<typename T>
71 SHZ_FORCE_INLINE T to() const noexcept {
72 return *reinterpret_cast<const T*>(this);
73 }
74
75 //! Conversion operator for accessing an existing pointer type as though it were a refrence to a SH4ZAM type.
76 SHZ_FORCE_INLINE CppType& deref(const auto* raw) noexcept {
77 return *const_cast<CppType*>(reinterpret_cast<const CppType*>(raw));
78 }
79
80 //! Returns the vector that is linearly interpolated between the two given vectors by the `0.0f-1.0f` factor, \p t.
81 SHZ_FORCE_INLINE static CppType lerp(const CppType& start, const CppType& end, float t) noexcept {
82 return shz_vec_lerp(start, end, t);
83 }
84
85 //! Compares each component of the vector to the edge. 0 returned in that component if x[i] < edge. Otherwise the component is 1.
86 template<typename T>
87 SHZ_FORCE_INLINE static CppType step(const CppType& vec, T&& edge) noexcept {
88 return shz_vec_step(vec, edge);
89 }
90
91 //! Returns a vector where each component is smoothly interpolated from 0 to 1 between edge0 and edge1.
92 template<typename T>
93 SHZ_FORCE_INLINE static CppType smoothstep(const CppType& vec, T&& edge0, T&& edge1) noexcept {
94 return shz_vec_smoothstep(vec, edge0, edge1);
95 }
96
97 //! Returns a vector where each component is smoothly interpolated from 0 to 1 between edge0 and edge1.
98 template<typename T>
99 SHZ_FORCE_INLINE static CppType smoothstep_safe(const CppType& vec, T&& edge0, T&& edge1) noexcept {
100 return shz_vec_smoothstep_safe(vec, edge0, edge1);
101 }
102
103#ifdef SHZ_CPP23
104 //! Overloaded subscript operator -- allows for indexing vectors like an array.
105 SHZ_FORCE_INLINE decltype(auto) operator[](this auto&& self, size_t index) noexcept {
106 return std::forward_like<decltype(self)>(self.e[index]);
107 }
108
109 //! Returns an iterator to the beginning of the vector -- For STL support.
110 SHZ_FORCE_INLINE auto begin(this auto&& self) noexcept {
111 return std::forward_like<decltype(self)>(&self[0]);
112 }
113
114 //! Returns an iterator to the end of the vector -- For STL support.
115 SHZ_FORCE_INLINE auto end(this auto&& self) noexcept {
116 return std::forward_like<decltype(self)>(&self[Rows]);
117 }
118
119 //! Overloaded space-ship operator, for generic lexicographical comparison of vectors.
120 friend auto operator<=>(const CppType& lhs, const CppType& rhs) noexcept {
122 }
123
124 //! Generic overloaded operator for assigning a generic "this" type to volatile reference to base C type.
125 template<typename T>
126 SHZ_FORCE_INLINE auto&& operator=(this T&& self, volatile CType other) noexcept {
127 const_cast<std::remove_cvref_t<T>&>(self) = CppType(const_cast<CType&>(other));
128 return std::forward<T>(self);
129 }
130#endif
131
132 //! Overloaded equality operator, for comparing vectors.
133 friend bool operator==(const CppType& lhs, const CppType& rhs) noexcept {
134 return shz_vec_equal(lhs, rhs);
135 }
136
137 //! Overloaded unary negation operator, returns the negated vector.
138 friend CppType operator-(const CppType& vec) noexcept {
139 return vec.neg();
140 }
141
142 //! Overloaded operator for adding and accumulating a vector onto another.
143 SHZ_FORCE_INLINE CppType& operator+=(const CppType& other) noexcept {
144 *static_cast<CppType*>(this) = *static_cast<CppType*>(this) + other;
145 return *static_cast<CppType*>(this);
146 }
147
148 //! Overloaded subtraction assignment operator, subtracts a vector from the left-hand vector.
149 SHZ_FORCE_INLINE CppType& operator-=(const CppType& other) noexcept {
150 *static_cast<CppType*>(this) = *static_cast<CppType*>(this) - other;
151 return *static_cast<CppType*>(this);
152 }
153
154 //! Overloaded multiplication assignment operator, multiplies and accumulates a vector onto the left-hand vector.
155 SHZ_FORCE_INLINE CppType& operator*=(const CppType& other) noexcept {
156 *static_cast<CppType*>(this) = *static_cast<CppType*>(this) * other;
157 return *static_cast<CppType*>(this);
158 }
159
160 //! Overloaded division assignment operator, divides the left vector by the right, assigning the left to the result.
161 SHZ_FORCE_INLINE CppType& operator/=(const CppType& other) noexcept {
162 *static_cast<CppType*>(this) = *static_cast<CppType*>(this) / other;
163 return *static_cast<CppType*>(this);
164 }
165
166 //! Overloaded multiplication assignment operator, multiplies and accumulates each vector component by the given scalar.
167 SHZ_FORCE_INLINE CppType& operator*=(float other) noexcept {
168 *static_cast<CppType*>(this) = *static_cast<CppType*>(this) * other;
169 return *static_cast<CppType*>(this);
170 }
171
172 //! Overloaded division assignment operator, dividing and assigning each vector component by the given scalar value.
173 SHZ_FORCE_INLINE CppType& operator/=(float other) noexcept {
174 *static_cast<CppType*>(this) = *static_cast<CppType*>(this) / other;
175 return *static_cast<CppType*>(this);
176 }
177
178 //! Swizzle oeprator which takes a compile-time list of indices as non-type template arguments for the index each element should use as its new value.
179 template<unsigned... Indices>
180 SHZ_FORCE_INLINE CppType swizzle() const noexcept {
181 return shz_vec_swizzle(*static_cast<const CppType*>(this), Indices...);
182 }
183
184 //! Returns a new vector whose components are the absolute value of the given vector.
185 SHZ_FORCE_INLINE CppType abs() const noexcept {
186 return shz_vec_abs(*static_cast<const CppType*>(this));
187 }
188
189 //! Returns a new vector whose components are the negative values of the given vector.
190 SHZ_FORCE_INLINE CppType neg() const noexcept {
191 return shz_vec_neg(*static_cast<const CppType*>(this));
192 }
193
194 //! Returns a new vector whose components are the reciprocal values of the given vector.
195 SHZ_FORCE_INLINE CppType inv() const noexcept {
196 return shz_vec_inv(*static_cast<const CppType*>(this));
197 }
198
199 //! Returns the maximum value of every element within the vector.
200 SHZ_FORCE_INLINE float max() const noexcept {
201 return shz_vec_max(*static_cast<const CppType*>(this));
202 }
203
204 //! Returns the minimum value of every element within the vector.
205 SHZ_FORCE_INLINE float min() const noexcept {
206 return shz_vec_min(*static_cast<const CppType*>(this));
207 }
208
209 //! Returns a new vector whose values are the clamped components of the given vector.
210 SHZ_FORCE_INLINE CppType clamp(float min, float max) const noexcept {
211 return shz_vec_clamp(*static_cast<const CppType*>(this), min, max);
212 }
213
214 //! Returns a new vector with the component-wise floor of the given vector.
215 SHZ_FORCE_INLINE CppType floor() const noexcept {
216 return shz_vec_floor(*static_cast<const CppType*>(this));
217 }
218
219 //! Returns a new vector with the component-wise ceil of the given vector.
220 SHZ_FORCE_INLINE CppType ceil() const noexcept {
221 return shz_vec_ceil(*static_cast<const CppType*>(this));
222 }
223
224 //! Returns a new vector with the component-wise rounding of the given vector.
225 SHZ_FORCE_INLINE CppType round() const noexcept {
226 return shz_vec_round(*static_cast<const CppType*>(this));
227 }
228
229 //! Returns a new vector with the fractional part of each component.
230 SHZ_FORCE_INLINE CppType fract() const noexcept {
231 return shz_vec_fract(*static_cast<const CppType*>(this));
232 }
233
234 //! Returns a new vector with the sign of each component (-1, 0, or 1).
235 SHZ_FORCE_INLINE CppType sign() const noexcept {
236 return shz_vec_sign(*static_cast<const CppType*>(this));
237 }
238
239 //! Returns a new vector with each component clamped to [0, 1].
240 SHZ_FORCE_INLINE CppType saturate() const noexcept {
241 return shz_vec_saturate(*static_cast<const CppType*>(this));
242 }
243
244 //! Returns a new vector with the component-wise minimum of two vectors.
245 SHZ_FORCE_INLINE CppType minv(const CppType& other) const noexcept {
246 return shz_vec_minv(*static_cast<const CppType*>(this), other);
247 }
248
249 //! Returns a new vector with the component-wise maximum of two vectors.
250 SHZ_FORCE_INLINE CppType maxv(const CppType& other) const noexcept {
251 return shz_vec_maxv(*static_cast<const CppType*>(this), other);
252 }
253
254 //! Returns a new vector whose components are the inverse square root of the given vector.
255 SHZ_FORCE_INLINE CppType inv_sqrtf() const noexcept {
256 return shz_vec_inv_sqrtf(*static_cast<const CppType*>(this));
257 }
258
259 //! Returns a new vector whose components are the square root of the given vector.
260 SHZ_FORCE_INLINE CppType sqrtf() const noexcept {
261 return shz_vec_sqrtf(*static_cast<const CppType*>(this));
262 }
263
264 //! Returns the dot product of the given vector and another.
265 SHZ_FORCE_INLINE float dot(const CppType& other) const noexcept {
266 return shz_vec_dot(*static_cast<const CppType*>(this), other);
267 }
268
269 //! Returns the dot product of the given vector against two others.
270 SHZ_FORCE_INLINE vec2 dot(const CppType& v1, const CppType& v2) const noexcept;
271
272 //! Returns the dot product of the given vector against three others.
273 SHZ_FORCE_INLINE vec3 dot(const CppType& v1, const CppType& v2, const CppType& v3) const noexcept;
274
275 //! Returns the magnitude of the given vector.
276 SHZ_FORCE_INLINE float magnitude() const noexcept {
277 return shz_vec_magnitude(*static_cast<const CppType*>(this));
278 }
279
280 //! Returns the squared magnitude of the given vector.
281 SHZ_FORCE_INLINE float magnitude_sqr() const noexcept {
282 return shz_vec_magnitude_sqr(*static_cast<const CppType*>(this));
283 }
284
285 //! Returns the inverse magnitude of the given vector.
286 SHZ_FORCE_INLINE float magnitude_inv() const noexcept {
287 return shz_vec_magnitude_inv(*static_cast<const CppType*>(this));
288 }
289
290 //! Returns the direction vector resulting from normalizing the given vector.
291 SHZ_FORCE_INLINE CppType direction() const noexcept {
292 return shz_vec_normalize(*static_cast<const CppType*>(this));
293 }
294
295 //! Returns the direction vector of a given vector, safely protecting against division-by-zero.
296 SHZ_FORCE_INLINE CppType direction_safe() const noexcept {
297 return shz_vec_normalize_safe(*static_cast<const CppType*>(this));
298 }
299
300 //! Normalizes the given vector.
301 SHZ_FORCE_INLINE void normalize() noexcept {
302 *static_cast<CppType*>(this) = shz_vec_normalize(*static_cast<const CppType*>(this));
303 }
304
305 //! Normalizes the given vector, safely protecting against division-by-zero.
306 SHZ_FORCE_INLINE void normalize_safe() noexcept {
307 *static_cast<CppType*>(this) = shz_vec_normalize_safe(*static_cast<const CppType*>(this));
308 }
309
310 //! Return the normalized vector.
311 SHZ_FORCE_INLINE CppType normalized() const noexcept {
312 return shz_vec_normalize(*static_cast<const CppType*>(this));
313 }
314
315 //! Return the normalized vector, safely protecting against division-by-zero.
316 SHZ_FORCE_INLINE CppType normalized_safe() const noexcept {
317 return shz_vec_normalize_safe(*static_cast<const CppType*>(this));
318 }
319
320 //! Returns the magnitude of the difference between two vectors as their distance.
321 SHZ_FORCE_INLINE float distance(const CppType& other) const noexcept {
322 return shz_vec_distance(*static_cast<const CppType*>(this), other);
323 }
324
325 //! Returns the value of the distance between two vectors squared (faster than actual distance)
326 SHZ_FORCE_INLINE float distance_sqr(const CppType& other) const noexcept {
327 return shz_vec_distance_sqr(*static_cast<const CppType*>(this), other);
328 }
329
330 //! Moves the given vector towards the target by the given \p maxdist.
331 SHZ_FORCE_INLINE CppType move(const CppType& target, float maxdist) const noexcept {
332 return shz_vec_move(*static_cast<const CppType*>(this), target, maxdist);
333 }
334
335 //! Returns the vector created from reflecting the given vector over the normal of a surface.
336 SHZ_FORCE_INLINE CppType reflect(const CppType& normal) const noexcept {
337 return shz_vec_reflect(*static_cast<const CppType*>(this), normal);
338 }
339
340 //! Returns the vector create from refracting the given incidence vector over the normal of a surface, using the given refraction ratio index.
341 SHZ_FORCE_INLINE CppType refract(const CppType& normal, float eta) const noexcept {
342 return shz_vec_refract(*static_cast<const CppType*>(this), normal, eta);
343 }
344
345 //! Returns the vector created from projecting the given vector onto another.
346 SHZ_FORCE_INLINE CppType project(const CppType& onto) const noexcept {
347 return shz_vec_project(*static_cast<const CppType*>(this), onto);
348 }
349
350 //! Returns the vector created from projecting the given vector onto another, safely protecting against division-by-zero.
351 SHZ_FORCE_INLINE CppType project_safe(const CppType& onto) const noexcept {
352 return shz_vec_project_safe(*static_cast<const CppType*>(this), onto);
353 }
354
355 //! Returns the angle between the given vector and another, in radians.
356 SHZ_FORCE_INLINE float angle_between(const CppType& other) const noexcept {
357 return shz_vec_angle_between(*static_cast<const CppType*>(this), other);
358 }
359
360 //! Returns the angle(s) created between the given vector axis and the +X axis, in radians.
361 SHZ_FORCE_INLINE auto angles() const noexcept {
362 return shz_vec_angles(*static_cast<const CppType*>(this));
363 }
364};
365
366//! Overloaded addition operator, adding two vectors together and returning the result.
367template<typename CRTP, typename C, size_t R>
368SHZ_FORCE_INLINE CRTP operator+(const vecN<CRTP, C, R>& lhs, const vecN<CRTP, C, R>& rhs) noexcept {
369 return shz_vec_add(lhs, rhs);
370}
371
372//! Overloaded subtraction operator, subtracting one vector from another, returning the result.
373template<typename CRTP, typename C, size_t R>
374SHZ_FORCE_INLINE CRTP operator-(const vecN<CRTP, C, R>& lhs, const vecN<CRTP, C, R>& rhs) noexcept {
375 return shz_vec_sub(lhs, rhs);
376}
377
378//! Overloaded multiplication operator, performing element-wise multiplication between two vectors, returning the resultant vector.
379template<typename CRTP, typename C, size_t R>
380SHZ_FORCE_INLINE CRTP operator*(const vecN<CRTP, C, R>& lhs, const vecN<CRTP, C, R>& rhs) noexcept {
381 return shz_vec_mul(lhs, rhs);
382}
383
384//! Overloaded division operator, returning the resulting vector from component-wise dividing the elements of \p lhs by \p rhs.
385template<typename CRTP, typename C, size_t R>
386SHZ_FORCE_INLINE CRTP operator/(const vecN<CRTP, C, R>& lhs, const vecN<CRTP, C, R>& rhs) noexcept {
387 return shz_vec_div(lhs, rhs);
388}
389
390//! Overloaded multiplication operator for scaling a vector by a scalar and returning the resulting vector.
391template<typename CRTP, typename C, size_t R>
392SHZ_FORCE_INLINE CRTP operator*(const vecN<CRTP, C, R>& lhs, float rhs) noexcept {
393 return shz_vec_scale(lhs, rhs);
394}
395
396//! Reverse overloaded multiplication operator for scaling a vector by a scalar and returning the resulting vector.
397template<typename CRTP, typename C, size_t R>
398SHZ_FORCE_INLINE CRTP operator*(float lhs, const vecN<CRTP, C, R>& rhs) noexcept {
399 return shz_vec_scale(rhs, lhs);
400}
401
402//! Overloaded division operator for component-wise dividing each element of the given vector by the given scalar.
403template<typename CRTP, typename C, size_t R>
404SHZ_FORCE_INLINE CRTP operator/(const vecN<CRTP, C, R>& lhs, float rhs) noexcept {
405 return shz_vec_scale(lhs, shz::invf(rhs));
406}
407
408//! Reverse overloaded division operator for component-wise dividing a vector whose elements have all been initialized to the scalar by the given vector.
409template<typename CRTP, typename C, size_t R>
410SHZ_FORCE_INLINE CRTP operator/(float lhs, const vecN<CRTP, C, R>& rhs) noexcept {
411 return shz_vec_div(CRTP(lhs), rhs);
412}
413
414/*! 2D Vector type
415 *
416 * C++ structure for representing a 2-dimensional vector.
417 *
418 * \sa shz::vecN, shz_vec2_t, shz::vec3, shz::vec4
419 */
420struct vec2: vecN<vec2, shz_vec2_t, 2> {
421 // Inherit parent constructors and operators.
422 using vecN::vecN;
423
424 // Unhide inherited overload assignment operators.
425 using vecN::operator=;
426
427 // Unhide inherited overloaded dot product methods.
428 using vecN::dot;
429
430 //! Default constructor: does nothing.
431 vec2() = default;
432
433 //! Single-value constructor: sets both components equal to \p v.
434 SHZ_FORCE_INLINE vec2(float v) noexcept:
435 vecN(shz_vec2_fill(v)) {}
436
437 //! Constructs a vec2 with the given values as components.
438 SHZ_FORCE_INLINE vec2(float x, float y) noexcept:
439 vecN(shz_vec2_init(x, y)) {}
440
441 //! Constructs a vec2 from the given angle of rotation from the +X axis.
442 SHZ_FORCE_INLINE vec2(const sincos& pair) noexcept:
444
445 //! Constructs a vec2 from the given angle of rotation from the +X axis, in radians.
446 SHZ_FORCE_INLINE static vec2 from_angle(float rads) noexcept {
447 return shz_vec2_from_angle(rads);
448 }
449
450 //! Constructs a vec2 from the given angle of rotation from the +X axis, in degrees.
451 SHZ_FORCE_INLINE static vec2 from_angle_deg(float deg) noexcept {
453 }
454
455 //! C++ wrapper for shz_vec2_cross().
456 SHZ_FORCE_INLINE float cross(const vec2& other) const noexcept {
457 return shz_vec2_cross(*this, other);
458 }
459
460 //! C++ wrapper for shz_vec2_rotate().
461 SHZ_FORCE_INLINE vec2 rotate(float radians) const noexcept {
462 return shz_vec2_rotate(*this, radians);
463 }
464};
465
466//! C++ alias for vec2 for those who like POSIX-style.
467using vec2_t = vec2;
468
469/*! 3D Vector type
470 *
471 * C++ structure for representing a 3-dimensional vector.
472 *
473 * \sa shz::vecN, shz_vec2_t, shz::vec2, shz::vec4
474 */
475struct vec3: vecN<vec3, shz_vec3_t, 3> {
476 // Inherit parent constructors and operators.
477 using vecN::vecN;
478
479 // Unhide inherited overloaded dot product methods.
480 using vecN::dot;
481
482 // Unhide inherited overloaded assignment operators.
483 using vecN::operator=;
484
485 //! Default constructor: does nothing
486 vec3() = default;
487
488 //! C constructor: constructs a C++ vec3 from a C shz_vec3_t.
489 SHZ_FORCE_INLINE vec3(const shz_vec3_t& other) noexcept:
490 vecN(other) {}
491
492 //! Single-value constructor: initializes all components to \p v.
493 SHZ_FORCE_INLINE vec3(float v) noexcept:
494 vecN(shz_vec3_fill(v)) {}
495
496 //! Value constructor: initializes each component to its given value.
497 SHZ_FORCE_INLINE vec3(float x, float y, float z) noexcept:
498 vecN(shz_vec3_init(x, y, z)) {}
499
500 //! Constructs a vec3 from a shz::vec2 and a scalar value for its z component.
501 SHZ_FORCE_INLINE vec3(const shz::vec2& xy, float z) noexcept:
502 vecN(shz_vec2_vec3(xy, z)) {}
503
504 //! Constructs a vec3 from a scalar as its x component and a shz::vec2 as its Y and Z components.
505 SHZ_FORCE_INLINE vec3(float x, const shz::vec2& yz) noexcept:
506 vecN(shz_vec3_init(x, yz.x, yz.y)) {}
507
508 //! Returns a 3D vector which forms the given angles with the +X axis.
509 SHZ_FORCE_INLINE vec3(const sincos& azimuth, const sincos& elevation) noexcept:
511
512/*! \name Rotations
513 \brief Routines for rotating a given vector.
514
515 \warning
516 These should only be used for one-off rotations, as it's much faster to apply the
517 same rotation against a batch of multiple vectors by going through the XMTRX API.
518
519 @{
520*/
521 /*! Rotates a 3D vector about the X axis by the given number of radians.
522
523 \sa shz::xmtrx::apply_rotation_x()
524 */
525 SHZ_FORCE_INLINE vec3 rotate_x(float angle) const noexcept {
526 return shz_vec3_rotate_x(*this, angle);
527 }
528
529 /*! Rotates a 3D vector about the Y axis by the given number of radians.
530
531 \sa shz::xmtrx::apply_rotation_y()
532 */
533 SHZ_FORCE_INLINE vec3 rotate_y(float angle) const noexcept {
534 return shz_vec3_rotate_y(*this, angle);
535 }
536
537 /*! Rotates a 3D vector about the Z axis by the given number of radians.
538
539 \sa shz::xmtrx::apply_rotation_z()
540 */
541 SHZ_FORCE_INLINE vec3 rotate_z(float angle) const noexcept {
542 return shz_vec3_rotate_z(*this, angle);
543 }
544//! @}
545
546 //! Returns 2 3D vectors which are normalized and orthogonal to the two input vectors as a std::pair<>.
547 SHZ_FORCE_INLINE static auto orthonormalize(const vec3& in1, const vec3& in2) noexcept {
548 vec3 out1, out2;
549 shz_vec3_orthonormalize(in1, in2, &out1, &out2);
550 return std::make_pair(out1, out2);
551 }
552
553 //! Returns 2 3D vectors which are normalized and orthogonal to the two input vectors via output pointers.
554 SHZ_FORCE_INLINE static void orthonormalize(const vec3& in1, const vec3& in2, vec3* out1, vec3* out2) noexcept {
555 shz_vec3_orthonormalize(in1, in2, out1, out2);
556 }
557
558 //! Calculates the cubic hermite interpolation between two vectors and their tangents.
559 SHZ_FORCE_INLINE static vec3 cubic_hermite(const vec3& v1, const vec3& tangent1, const vec3& v2, const vec3& tangent2, float amount) noexcept {
560 return shz_vec3_cubic_hermite(v1, tangent1, v2, tangent2, amount);
561 }
562
563 // Returns the inner 2D vector, <X, Y>, as a C++ vector.
564 SHZ_FORCE_INLINE vec2 xy() const noexcept {
565 return shz_vec3_t::xy;
566 }
567
568 //! Returns a 3D vector which forms the given angles with the +X axis, in radians.
569 SHZ_FORCE_INLINE static vec3 from_angles(float azimuth_rads, float elevation_rads) noexcept {
570 return shz_vec3_from_angles(azimuth_rads, elevation_rads);
571 }
572
573 //! Returns a 3D vector which forms the given angles with the +X axis, in degrees.
574 SHZ_FORCE_INLINE static vec3 from_angles_deg(float azimuth_deg, float elevation_deg) noexcept {
575 return shz_vec3_from_angles_deg(azimuth_deg, elevation_deg);
576 }
577
578 //! Returns a 3D vector which forms the given angles with the +X axis.
579 SHZ_FORCE_INLINE vec3 cross(const vec3& other) const noexcept {
580 return shz_vec3_cross(*this, other);
581 }
582
583 //! Returns the 3D vector "triple product" between the given vector and vectors \p a and \p b.
584 SHZ_FORCE_INLINE float triple(const vec3& b, const vec3& c) const noexcept {
585 return shz_vec3_triple(*this, b, c);
586 }
587
588 //! Returns a 3D vector which is perpendicular to this vector.
589 SHZ_FORCE_INLINE vec3 perp() const noexcept {
590 return shz_vec3_perp(*this);
591 }
592
593 //! Returns the 3D reject vector of the given vector and another.
594 SHZ_FORCE_INLINE vec3 reject(const vec3& onto) const noexcept {
595 return shz_vec3_reject(*this, onto);
596 }
597
598 //! Computes the barycentric coordinates `<u, v, w>` for the given 3D vector, within the plane of the triangle formed by the given vertices, \p a, \p b, and \p c.
599 SHZ_FORCE_INLINE vec3 barycenter(const vec3& a, const vec3& b, const vec3& c) const noexcept {
600 return shz_vec3_barycenter(*this, a, b, c);
601 }
602};
603
604//! C++ alias for vec3 for those who like POSIX-style.
605using vec3_t = vec3;
606
607/*! 4D Vector type
608 *
609 * C++ structure for representing a 4-dimensional vector.
610 *
611 * \sa shz::vecN, shz_vec4_t, shz::vec2, shz::vec3
612 */
613struct vec4: vecN<vec4, shz_vec4_t, 4> {
614 // Inherit parent constructors and operators.
615 using vecN::vecN;
616
617 // Unhide inherited overloaded dot product methods.
618 using vecN::dot;
619
620 // Unhide inherited overload assignment operators.
621 using vecN::operator=;
622
623 //! Default constructor: does nothing.
624 vec4() = default;
625
626 //! C Constructor: initializes a C++ shz::vec4 from a C shz_vec4_t.
627 SHZ_FORCE_INLINE vec4(const shz_vec4_t& other) noexcept:
628 vecN(other) {}
629
630 //! Single-value constructor: initializes each element to the given value.
631 SHZ_FORCE_INLINE vec4(float v) noexcept:
632 vecN(shz_vec4_fill(v)) {}
633
634 //! Value constructor: initializes each element to its corresponding parameter value.
635 SHZ_FORCE_INLINE vec4(float x, float y, float z, float w) noexcept:
636 vecN(shz_vec4_init(x, y, z, w)) {}
637
638 //! Constructs a 4D vector with a 2D vector providing the X and Y coordinates and scalars providing Z and W.
639 SHZ_FORCE_INLINE vec4(const shz::vec2& xy, float z, float w) noexcept:
640 vecN(shz_vec2_vec4(xy, z, w)) {}
641
642 //! Constructs a 4D vector with scalars providing X and W coordinates and a 2D vector providing Y and Z.
643 SHZ_FORCE_INLINE vec4(float x, const shz::vec2& yz, float w) noexcept:
644 vecN(shz_vec4_init(x, yz.x, yz.y, w)) {}
645
646 //! Constructs a 4D vector with scalars providing X and Y coordinaets and a 2D vector providing Z and W.
647 SHZ_FORCE_INLINE vec4(float x, float y, const shz::vec2& zw) noexcept:
648 vecN(shz_vec4_init(x, y, zw.x, zw.y )) {}
649
650 //! Constructs a 4D vector from the components provided by the given pair of 2D vectors.
651 SHZ_FORCE_INLINE vec4(const shz::vec2& xy, const shz::vec2& zw) noexcept:
652 vecN(shz_vec4_init(xy.x, xy.y, zw.x, zw.y)) {}
653
654 //! Constructs a 4D vector with the X, Y, and Z components given by a 3D vector and W given by a scalar.
655 SHZ_FORCE_INLINE vec4(const shz::vec3& xyz, float w) noexcept:
656 vecN(shz_vec3_vec4(xyz, w)) {}
657
658 //! Constructs a 4D vector with the X component given by a scalar and the Y, Z, and W components given by a 3D vector.
659 SHZ_FORCE_INLINE vec4(float x, const shz::vec3& yzw) noexcept:
660 vecN(shz_vec4_init(x, yzw.x, yzw.y, yzw.z)) {}
661
662 // Returns the inner 2D vector, <X, Y>, as a C++ vector.
663 SHZ_FORCE_INLINE vec2 xy() const noexcept {
664 return shz_vec4_t::xy;
665 }
666
667 // Returns the inner 2D vector, <Z, W>, as a C++ vector.
668 SHZ_FORCE_INLINE vec2 zw() const noexcept {
669 return shz_vec4_t::zw;
670 }
671
672 // Returns the inner 3D vector, <X, Y, Z>, as a C++ vector.
673 SHZ_FORCE_INLINE vec3 xyz() const noexcept {
674 return shz_vec4_t::xyz;
675 }
676};
677
678//! C++ alias for vec4 for those who like POSIX-style.s
679using vec4_t = vec4;
680
681template<typename CRTP, typename C, size_t R>
682SHZ_FORCE_INLINE vec2 vecN<CRTP, C, R>::dot(const CppType& v1, const CppType& v2) const noexcept {
683 return shz_vec_dot2(*static_cast<const CRTP*>(this), v1, v2);
684}
685
686template<typename CRTP, typename C, size_t R>
687SHZ_FORCE_INLINE vec3 vecN<CRTP, C, R>::dot(const CppType& v1, const CppType& v2, const CppType& v3) const noexcept {
688 return shz_vec_dot3(*static_cast<const CRTP*>(this), v1, v2, v3);
689}
690
691}
692
693#endif // SHZ_VECTOR_HPP
Namespace enclosing the SH4ZAM C++ API.
Definition shz_cdefs.hpp:21
CRTP operator+(const vecN< CRTP, C, R > &lhs, const vecN< CRTP, C, R > &rhs) noexcept
Overloaded addition operator, adding two vectors together and returning the result.
CRTP operator*(float lhs, const vecN< CRTP, C, R > &rhs) noexcept
Reverse overloaded multiplication operator for scaling a vector by a scalar and returning the resulti...
CRTP operator-(const vecN< CRTP, C, R > &lhs, const vecN< CRTP, C, R > &rhs) noexcept
Overloaded subtraction operator, subtracting one vector from another, returning the result.
CRTP operator*(const vecN< CRTP, C, R > &lhs, float rhs) noexcept
Overloaded multiplication operator for scaling a vector by a scalar and returning the resulting vecto...
CRTP operator/(const vecN< CRTP, C, R > &lhs, float rhs) noexcept
Overloaded division operator for component-wise dividing each element of the given vector by the give...
CRTP operator/(const vecN< CRTP, C, R > &lhs, const vecN< CRTP, C, R > &rhs) noexcept
Overloaded division operator, returning the resulting vector from component-wise dividing the element...
CRTP operator/(float lhs, const vecN< CRTP, C, R > &rhs) noexcept
Reverse overloaded division operator for component-wise dividing a vector whose elements have all bee...
constexpr auto invf
C++ alias for shz_invf().
CRTP operator*(const vecN< CRTP, C, R > &lhs, const vecN< CRTP, C, R > &rhs) noexcept
Overloaded multiplication operator, performing element-wise multiplication between two vectors,...
shz_vec3_t shz_vec3_from_angles_deg(float azimuth, float elevation) noexcept
Returns the 3D unit vector representing the given rotation angles relative to the positive X axis in ...
shz_vec2_t shz_vec2_from_angle(float radians) noexcept
Returns the 2D unit vector representing a rotation from the positive X axis in radians.
shz_vec3_t shz_vec3_from_angles(float azimuth, float elevation) noexcept
Returns the 3D unit vector representing the given rotation angles relative to the positive X axis in ...
shz_vec2_t shz_vec2_from_angle_deg(float degrees) noexcept
Returns the 2D unit vector representing a rotation from the positive X axis in degrees.
C++ sine/cosine approximation pairs.
Definition shz_trig.hpp:44
2D Vector type
vec2(float v) noexcept
Single-value constructor: sets both components equal to v.
vec2()=default
Default constructor: does nothing.
vec2(float x, float y) noexcept
Constructs a vec2 with the given values as components.
vec2(const sincos &pair) noexcept
Constructs a vec2 from the given angle of rotation from the +X axis.
float cross(const vec2 &other) const noexcept
C++ wrapper for shz_vec2_cross().
static vec2 from_angle_deg(float deg) noexcept
Constructs a vec2 from the given angle of rotation from the +X axis, in degrees.
vec2 rotate(float radians) const noexcept
C++ wrapper for shz_vec2_rotate().
static vec2 from_angle(float rads) noexcept
Constructs a vec2 from the given angle of rotation from the +X axis, in radians.
3D Vector type
vec3 barycenter(const vec3 &a, const vec3 &b, const vec3 &c) const noexcept
Computes the barycentric coordinates <u, v, w> for the given 3D vector, within the plane of the trian...
vec3 reject(const vec3 &onto) const noexcept
Returns the 3D reject vector of the given vector and another.
vec3(const sincos &azimuth, const sincos &elevation) noexcept
Returns a 3D vector which forms the given angles with the +X axis.
static void orthonormalize(const vec3 &in1, const vec3 &in2, vec3 *out1, vec3 *out2) noexcept
Returns 2 3D vectors which are normalized and orthogonal to the two input vectors via output pointers...
vec3(float x, float y, float z) noexcept
Value constructor: initializes each component to its given value.
static vec3 cubic_hermite(const vec3 &v1, const vec3 &tangent1, const vec3 &v2, const vec3 &tangent2, float amount) noexcept
Calculates the cubic hermite interpolation between two vectors and their tangents.
static auto orthonormalize(const vec3 &in1, const vec3 &in2) noexcept
Returns 2 3D vectors which are normalized and orthogonal to the two input vectors as a std::pair<>.
static vec3 from_angles_deg(float azimuth_deg, float elevation_deg) noexcept
Returns a 3D vector which forms the given angles with the +X axis, in degrees.
vec3(const shz::vec2 &xy, float z) noexcept
Constructs a vec3 from a shz::vec2 and a scalar value for its z component.
vec3 rotate_y(float angle) const noexcept
Rotates a 3D vector about the Y axis by the given number of radians.
vec3 cross(const vec3 &other) const noexcept
Returns a 3D vector which forms the given angles with the +X axis.
vec3(float v) noexcept
Single-value constructor: initializes all components to v.
vec3(const shz_vec3_t &other) noexcept
C constructor: constructs a C++ vec3 from a C shz_vec3_t.
vec3 rotate_z(float angle) const noexcept
Rotates a 3D vector about the Z axis by the given number of radians.
vec3(float x, const shz::vec2 &yz) noexcept
Constructs a vec3 from a scalar as its x component and a shz::vec2 as its Y and Z components.
vec3 perp() const noexcept
Returns a 3D vector which is perpendicular to this vector.
float triple(const vec3 &b, const vec3 &c) const noexcept
Returns the 3D vector "triple product" between the given vector and vectors a and b.
vec3()=default
Default constructor: does nothing.
static vec3 from_angles(float azimuth_rads, float elevation_rads) noexcept
Returns a 3D vector which forms the given angles with the +X axis, in radians.
vec3 rotate_x(float angle) const noexcept
Rotates a 3D vector about the X axis by the given number of radians.
4D Vector type
vec4(float x, float y, const shz::vec2 &zw) noexcept
Constructs a 4D vector with scalars providing X and Y coordinaets and a 2D vector providing Z and W.
vec4(float x, const shz::vec2 &yz, float w) noexcept
Constructs a 4D vector with scalars providing X and W coordinates and a 2D vector providing Y and Z.
vec4(float v) noexcept
Single-value constructor: initializes each element to the given value.
vec4(const shz::vec2 &xy, const shz::vec2 &zw) noexcept
Constructs a 4D vector from the components provided by the given pair of 2D vectors.
vec4(const shz_vec4_t &other) noexcept
C Constructor: initializes a C++ shz::vec4 from a C shz_vec4_t.
vec4(const shz::vec2 &xy, float z, float w) noexcept
Constructs a 4D vector with a 2D vector providing the X and Y coordinates and scalars providing Z and...
vec4(float x, const shz::vec3 &yzw) noexcept
Constructs a 4D vector with the X component given by a scalar and the Y, Z, and W components given by...
vec4(const shz::vec3 &xyz, float w) noexcept
Constructs a 4D vector with the X, Y, and Z components given by a 3D vector and W given by a scalar.
vec4()=default
Default constructor: does nothing.
vec4(float x, float y, float z, float w) noexcept
Value constructor: initializes each element to its corresponding parameter value.
Common C++ base structure inherited by all vector types.
CppType project(const CppType &onto) const noexcept
Returns the vector created from projecting the given vector onto another.
float magnitude_inv() const noexcept
Returns the inverse magnitude of the given vector.
T to() const noexcept
Conversion operator for going from a SH4ZAM vector type to another layout-compatible type.
float max() const noexcept
Returns the maximum value of every element within the vector.
CppType & operator-=(const CppType &other) noexcept
Overloaded subtraction assignment operator, subtracts a vector from the left-hand vector.
vecN(const vecN &other) noexcept=default
Default copy constructor.
CppType clamp(float min, float max) const noexcept
Returns a new vector whose values are the clamped components of the given vector.
CppType & operator*=(float other) noexcept
Overloaded multiplication assignment operator, multiplies and accumulates each vector component by th...
float min() const noexcept
Returns the minimum value of every element within the vector.
CppType round() const noexcept
Returns a new vector with the component-wise rounding of the given vector.
CppType project_safe(const CppType &onto) const noexcept
Returns the vector created from projecting the given vector onto another, safely protecting against d...
CppType maxv(const CppType &other) const noexcept
Returns a new vector with the component-wise maximum of two vectors.
CppType inv_sqrtf() const noexcept
Returns a new vector whose components are the inverse square root of the given vector.
static CppType smoothstep(const CppType &vec, T &&edge0, T &&edge1) noexcept
Returns a vector where each component is smoothly interpolated from 0 to 1 between edge0 and edge1.
static CppType from(const auto &raw) noexcept
Conversion operator for going from a layout-compatible vector type to a SH4ZAM vector type.
CppType ceil() const noexcept
Returns a new vector with the component-wise ceil of the given vector.
static constexpr size_t Rows
Number of rows.
float distance(const CppType &other) const noexcept
Returns the magnitude of the difference between two vectors as their distance.
CppType fract() const noexcept
Returns a new vector with the fractional part of each component.
CppType minv(const CppType &other) const noexcept
Returns a new vector with the component-wise minimum of two vectors.
CppType reflect(const CppType &normal) const noexcept
Returns the vector created from reflecting the given vector over the normal of a surface.
vecN(const CType &other) noexcept
Converting constructor from existing C instance.
CppType & operator+=(const CppType &other) noexcept
Overloaded operator for adding and accumulating a vector onto another.
friend CppType operator-(const CppType &vec) noexcept
Overloaded unary negation operator, returns the negated vector.
void normalize() noexcept
Normalizes the given vector.
CppType normalized_safe() const noexcept
Return the normalized vector, safely protecting against division-by-zero.
CppType & deref(const auto *raw) noexcept
Conversion operator for accessing an existing pointer type as though it were a refrence to a SH4ZAM t...
static constexpr size_t Cols
Number of columns.
float distance_sqr(const CppType &other) const noexcept
Returns the value of the distance between two vectors squared (faster than actual distance)
CppType & operator/=(float other) noexcept
Overloaded division assignment operator, dividing and assigning each vector component by the given sc...
vec2 dot(const CppType &v1, const CppType &v2) const noexcept
Returns the dot product of the given vector against two others.
void normalize_safe() noexcept
Normalizes the given vector, safely protecting against division-by-zero.
CppType swizzle() const noexcept
Swizzle oeprator which takes a compile-time list of indices as non-type template arguments for the in...
CppType direction_safe() const noexcept
Returns the direction vector of a given vector, safely protecting against division-by-zero.
static CppType step(const CppType &vec, T &&edge) noexcept
Compares each component of the vector to the edge. 0 returned in that component if x[i] < edge....
CppType saturate() const noexcept
Returns a new vector with each component clamped to [0, 1].
CppType floor() const noexcept
Returns a new vector with the component-wise floor of the given vector.
CppType & operator/=(const CppType &other) noexcept
Overloaded division assignment operator, divides the left vector by the right, assigning the left to ...
auto angles() const noexcept
Returns the angle(s) created between the given vector axis and the +X axis, in radians.
CppType sqrtf() const noexcept
Returns a new vector whose components are the square root of the given vector.
vecN(const volatile CType &other) noexcept
Converting constructor from existing volatile C instance.
CppType normalized() const noexcept
Return the normalized vector.
CppType abs() const noexcept
Returns a new vector whose components are the absolute value of the given vector.
static CppType smoothstep_safe(const CppType &vec, T &&edge0, T &&edge1) noexcept
Returns a vector where each component is smoothly interpolated from 0 to 1 between edge0 and edge1.
CppType refract(const CppType &normal, float eta) const noexcept
Returns the vector create from refracting the given incidence vector over the normal of a surface,...
CppType direction() const noexcept
Returns the direction vector resulting from normalizing the given vector.
float magnitude_sqr() const noexcept
Returns the squared magnitude of the given vector.
vec3 dot(const CppType &v1, const CppType &v2, const CppType &v3) const noexcept
Returns the dot product of the given vector against three others.
float dot(const CppType &other) const noexcept
Returns the dot product of the given vector and another.
CppType neg() const noexcept
Returns a new vector whose components are the negative values of the given vector.
vecN() noexcept=default
Default constructor, does nothing.
float magnitude() const noexcept
Returns the magnitude of the given vector.
friend bool operator==(const CppType &lhs, const CppType &rhs) noexcept
Overloaded equality operator, for comparing vectors.
static CppType lerp(const CppType &start, const CppType &end, float t) noexcept
Returns the vector that is linearly interpolated between the two given vectors by the 0....
CppType sign() const noexcept
Returns a new vector with the sign of each component (-1, 0, or 1).
float angle_between(const CppType &other) const noexcept
Returns the angle between the given vector and another, in radians.
CppType move(const CppType &target, float maxdist) const noexcept
Moves the given vector towards the target by the given maxdist.
CppType inv() const noexcept
Returns a new vector whose components are the reciprocal values of the given vector.
CppType & operator*=(const CppType &other) noexcept
Overloaded multiplication assignment operator, multiplies and accumulates a vector onto the left-hand...