jaulib v1.3.6
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
vec2f.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2022-2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#ifndef JAU_VEC2F_HPP_
25#define JAU_VEC2F_HPP_
26
27#include <cmath>
28#include <cstdarg>
29#include <cassert>
30#include <limits>
31#include <string>
32#include <algorithm>
33#include <iostream>
34
35#include <jau/float_math.hpp>
36
37namespace jau::math {
38
39 /** \addtogroup Math
40 *
41 * @{
42 */
43
44 /**
45 * 2D vector using two value_type components.
46 *
47 * Component and overall alignment is natural as sizeof(value_type),
48 * i.e. sizeof(value_type) == alignof(value_type)
49 */
50 template<typename Value_type,
51 std::enable_if_t<std::is_floating_point_v<Value_type> &&
52 sizeof(Value_type) == alignof(Value_type), bool> = true>
53 class alignas(sizeof(Value_type)) Vector2F {
54 public:
57 typedef const value_type* const_pointer;
61 typedef const value_type* const_iterator;
62
63 /** value alignment is sizeof(value_type) */
64 constexpr static int value_alignment = sizeof(value_type);
65
66 /** Number of value_type components */
67 constexpr static const size_t components = 2;
68
69 /** Size in bytes with value_alignment */
70 constexpr static const size_t byte_size = components * sizeof(value_type);
71
72 constexpr static const value_type zero = value_type(0);
73 constexpr static const value_type one = value_type(1);
74
77
78 static constexpr_cxx26 Vector2F from_length_angle(const value_type magnitude, const value_type radians) noexcept {
79 return Vector2F(magnitude * std::cos(radians), magnitude * std::sin(radians));
80 }
81
82 constexpr Vector2F() noexcept
83 : x(zero), y(zero) {}
84
85 constexpr Vector2F(const value_type v) noexcept
86 : x(v), y(v) {}
87
88 constexpr Vector2F(const value_type x_, const value_type y_) noexcept
89 : x(x_), y(y_) {}
90
91 constexpr Vector2F(const Vector2F& o) noexcept = default;
92 constexpr Vector2F(Vector2F&& o) noexcept = default;
93 constexpr Vector2F& operator=(const Vector2F&) noexcept = default;
94 constexpr Vector2F& operator=(Vector2F&&) noexcept = default;
95
96 constexpr Vector2F copy() noexcept { return Vector2F(*this); }
97
98 /** Returns read-only component */
99 constexpr value_type operator[](size_t i) const noexcept {
100 assert(i < 2);
101 return (&x)[i];
102 }
103
104 explicit operator const_pointer() const noexcept { return &x; }
105 constexpr const_iterator cbegin() const noexcept { return &x; }
106
107 /** Returns writeable reference to component */
108 constexpr reference operator[](size_t i) noexcept {
109 assert(i < 2);
110 return (&x)[i];
111 }
112
113 explicit operator pointer() noexcept { return &x; }
114 constexpr iterator begin() noexcept { return &x; }
115
116 /** xy = this, returns xy. */
117 constexpr iterator get(iterator xy) const noexcept {
118 xy[0] = x;
119 xy[1] = y;
120 return xy;
121 }
122
123 constexpr bool operator==(const Vector2F& rhs ) const noexcept {
124 if( this == &rhs ) {
125 return true;
126 }
127 return jau::is_zero(x - rhs.x) && jau::is_zero(y - rhs.y);
128 }
129 /** TODO
130 constexpr bool operator<=>(const vec2f_t& rhs ) const noexcept {
131 return ...
132 } */
133
134 constexpr Vector2F& set(const value_type vx, const value_type vy) noexcept
135 { x=vx; y=vy; return *this; }
136
137 /** this = xy, returns this. */
138 constexpr Vector2F& set(const_iterator xy) noexcept
139 { x=xy[0]; y=xy[1]; return *this; }
140
141 /** this = this + {sx, sy}, returns this. */
142 constexpr Vector2F& add(const value_type dx, const value_type dy) noexcept
143 { x+=dx; y+=dy; return *this; }
144
145 /** this = this * {sx, sy}, returns this. */
146 constexpr Vector2F& mul(const value_type sx, const value_type sy) noexcept
147 { x*=sx; y*=sy; return *this; }
148
149 /** this = this * s, returns this. */
150 constexpr Vector2F& scale(const value_type s) noexcept
151 { x*=s; y*=s; return *this; }
152
153 /** this = this + rhs, returns this. */
154 constexpr Vector2F& operator+=(const Vector2F& rhs ) noexcept {
155 x+=rhs.x; y+=rhs.y;
156 return *this;
157 }
158
159 /** this = this - rhs, returns this. */
160 constexpr Vector2F& operator-=(const Vector2F& rhs ) noexcept {
161 x-=rhs.x; y-=rhs.y;
162 return *this;
163 }
164
165 /**
166 * Scale this vector with given scale factor
167 * @param s scale factor
168 * @return this instance
169 */
170 constexpr Vector2F& operator*=(const value_type s ) noexcept {
171 x*=s; y*=s;
172 return *this;
173 }
174
175 /**
176 * Divide this vector with given scale factor
177 * @param s scale factor
178 * @return this instance
179 */
180 constexpr Vector2F& operator/=(const value_type s ) noexcept {
181 x/=s; y/=s;
182 return *this;
183 }
184
185 /** Rotates this vector in place, returns *this */
186 constexpr_cxx26 Vector2F& rotate(const value_type radians, const Vector2F& ctr) noexcept {
187 return rotate(std::sin(radians), std::cos(radians), ctr);
188 }
189
190 /** Rotates this vector in place, returns *this */
191 constexpr Vector2F& rotate(const value_type sin, const value_type cos, const Vector2F& ctr) noexcept {
192 const value_type x0 = x - ctr.x;
193 const value_type y0 = y - ctr.y;
194 x = x0 * cos - y0 * sin + ctr.x;
195 y = x0 * sin + y0 * cos + ctr.y;
196 return *this;
197 }
198
199 /** Rotates this vector in place, returns *this */
200 constexpr_cxx26 Vector2F& rotate(const value_type radians) noexcept {
201 return rotate(std::sin(radians), std::cos(radians));
202 }
203
204 /** Rotates this vector in place, returns *this */
205 constexpr Vector2F& rotate(const value_type sin, const value_type cos) noexcept {
206 const value_type x0 = x;
207 x = x0 * cos - y * sin;
208 y = x0 * sin + y * cos;
209 return *this;
210 }
211
212 std::string toString() const noexcept { return std::to_string(x)+", "+std::to_string(y); }
213
214 constexpr bool is_zero() const noexcept {
215 return jau::is_zero(x) && jau::is_zero(y);
216 }
217
218 /**
219 * Return the squared length of this vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
220 */
221 constexpr value_type length_sq() const noexcept {
222 return x*x + y*y;
223 }
224
225 /**
226 * Return the length of this vector, a.k.a the <i>norm</i> or <i>magnitude</i>
227 */
228 constexpr value_type length() const noexcept {
229 return std::sqrt(length_sq());
230 }
231
232 /** Normalize this vector in place, returns *this */
233 constexpr Vector2F& normalize() noexcept {
234 const value_type lengthSq = length_sq();
235 if ( jau::is_zero( lengthSq ) ) {
236 x = zero;
237 y = zero;
238 } else {
239 const value_type invSqr = one / std::sqrt(lengthSq);
240 x *= invSqr;
241 y *= invSqr;
242 }
243 return *this;
244 }
245
246 /**
247 * Return the direction angle of this vector in radians
248 */
250 // Utilize atan2 taking y=sin(a) and x=cos(a), resulting in proper direction angle for all quadrants.
251 return std::atan2( y, x );
252 }
253
254 /**
255 * Return the squared distance between this vector and the given one.
256 * <p>
257 * When comparing the relative distance between two points it is usually sufficient to compare the squared
258 * distances, thus avoiding an expensive square root operation.
259 * </p>
260 */
261 constexpr value_type dist_sq(const Vector2F& o) const noexcept {
262 const value_type dx = x - o.x;
263 const value_type dy = y - o.y;
264 return dx*dx + dy*dy;
265 }
266
267 /**
268 * Return the distance between this vector and the given one.
269 */
270 constexpr value_type dist(const Vector2F& o) const noexcept {
271 return std::sqrt(dist_sq(o));
272 }
273
274 /**
275 * Return the dot product of this vector and the given one
276 * @return the dot product as value_type
277 */
278 constexpr value_type dot(const Vector2F& o) const noexcept {
279 return x*o.x + y*o.y;
280 }
281
282 /**
283 * Returns cross product of this vectors and the given one, i.e. *this x o.
284 *
285 * The 2D cross product is identical with the 2D perp dot product.
286 *
287 * @return the resulting scalar
288 */
289 constexpr value_type cross(const Vector2F& o) const noexcept {
290 return x * o.y - y * o.x;
291 }
292
293 /**
294 * Return the cosines of the angle between two vectors
295 */
296 constexpr value_type cos_angle(const Vector2F& o) const noexcept {
297 return dot(o) / ( length() * o.length() ) ;
298 }
299
300 /**
301 * Return the angle between two vectors in radians
302 */
303 constexpr_cxx26 value_type angle(const Vector2F& o) const noexcept {
304 return std::acos( cos_angle(o) );
305 }
306
307 /**
308 * Return the counter-clock-wise (CCW) normal of this vector, i.e. perp(endicular) vector
309 */
310 constexpr Vector2F normal_ccw() const noexcept {
311 return Vector2F(-y, x);
312 }
313
314 constexpr_cxx23 bool intersects(const Vector2F& o) const noexcept {
315 const value_type eps = std::numeric_limits<value_type>::epsilon();
316 if( std::abs(x-o.x) >= eps || std::abs(y-o.y) >= eps ) {
317 return false;
318 }
319 return true;
320 }
321 };
322
323 template<typename T,
324 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
325 constexpr Vector2F<T> operator+(const Vector2F<T>& lhs, const Vector2F<T>& rhs ) noexcept {
326 // Returning a Vector2F<T> object from the returned reference of operator+=()
327 // may hinder copy-elision or "named return value optimization" (NRVO).
328 // return Vector2F<T>(lhs) += rhs;
329
330 // Returning named object allows copy-elision (NRVO),
331 // only one object is created 'on target'.
332 Vector2F<T> r(lhs); r += rhs; return r;
333 }
334
335 template<typename T,
336 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
337 constexpr Vector2F<T> operator-(const Vector2F<T>& lhs, const Vector2F<T>& rhs ) noexcept {
338 Vector2F<T> r(lhs); r -= rhs; return r;
339 }
340
341 template<typename T,
342 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
343 constexpr Vector2F<T> operator-(const Vector2F<T>& lhs) noexcept {
344 Vector2F<T> r(lhs);
345 r *= -1;
346 return r;
347 }
348
349 template<typename T,
350 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
351 constexpr Vector2F<T> operator*(const Vector2F<T>& lhs, const T s ) noexcept {
352 Vector2F<T> r(lhs); r *= s; return r;
353 }
354
355 template<typename T,
356 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
357 constexpr Vector2F<T> operator*(const T s, const Vector2F<T>& rhs) noexcept {
358 Vector2F<T> r(rhs); r *= s; return r;
359 }
360
361 template<typename T,
362 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
363 constexpr Vector2F<T> operator/(const Vector2F<T>& lhs, const T s ) noexcept {
364 Vector2F<T> r(lhs); r /= s; return r;
365 }
366
367 template<typename T,
368 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
369 constexpr Vector2F<T> min(const Vector2F<T>& lhs, const Vector2F<T>& rhs) noexcept {
370 return Vector2F<T>(std::min(lhs.x, rhs.x), std::min(lhs.y, rhs.y));
371 }
372
373 template<typename T,
374 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
375 constexpr Vector2F<T> max(const Vector2F<T>& lhs, const Vector2F<T>& rhs) noexcept {
376 return Vector2F<T>(std::max(lhs.x, rhs.x), std::max(lhs.y, rhs.y));
377 }
378
379 template<typename T,
380 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
381 std::ostream& operator<<(std::ostream& out, const Vector2F<T>& v) noexcept {
382 return out << v.toString();
383 }
384
385 static_assert(sizeof(float) == alignof(float)); // natural alignment (reconsider otherwise)
386
388 static_assert(2 == Vec2f::components);
389 static_assert(sizeof(float) == Vec2f::value_alignment);
390 static_assert(sizeof(float) == alignof(Vec2f));
391 static_assert(sizeof(float)*2 == Vec2f::byte_size);
392 static_assert(sizeof(float)*2 == sizeof(Vec2f));
393
394 /**
395 * Point2F alias of Vector2F
396 */
397 template<typename Value_type,
398 std::enable_if_t<std::is_floating_point_v<Value_type> &&
399 sizeof(Value_type) == alignof(Value_type), bool> = true>
401
403 static_assert(2 == Point2f::components);
404 static_assert(sizeof(float) == Point2f::value_alignment);
405 static_assert(sizeof(float) == alignof(Point2f));
406 static_assert(sizeof(float)*2 == Point2f::byte_size);
407 static_assert(sizeof(float)*2 == sizeof(Point2f));
408
409 /**
410 * Simple compound denoting a ray.
411 *
412 * Component and overall alignment is as sizeof(value_type), i.e. packed.
413 *
414 * A ray, also known as a half line, consists out of it's <i>origin</i>
415 * and <i>direction</i>. Hence it is bound to only the <i>origin</i> side,
416 * where the other end is +infinitive.
417 * <pre>
418 * R(t) = R0 + Rd * t with R0 origin, Rd direction and t > 0.0
419 * </pre>
420 */
421 template<typename Value_type,
422 std::enable_if_t<std::is_floating_point_v<Value_type> &&
423 sizeof(Value_type) == alignof(Value_type), bool> = true>
424 class alignas(sizeof(Value_type)) Ray2F {
425 public:
428 typedef const value_type* const_pointer;
429
430 /** value alignment is sizeof(value_type) */
431 constexpr static int value_alignment = sizeof(value_type);
432
433 /** Number of value_type components */
434 constexpr static const size_t components = 4;
435
436 /** Size in bytes with value_alignment */
437 constexpr static const size_t byte_size = components * sizeof(value_type);
438
439 /** Origin of Ray. */
441
442 /** Normalized direction vector of ray. */
444
445 std::string toString() const noexcept { return "Ray[orig "+orig.toString()+", dir "+dir.toString() +"]"; }
446 };
447
448 template<typename T,
449 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
450 std::ostream& operator<<(std::ostream& out, const Ray2F<T>& v) noexcept {
451 return out << v.toString();
452 }
453
455 static_assert(4 == Ray2f::components);
456 static_assert(sizeof(float) == Ray2f::value_alignment);
457 static_assert(sizeof(float) == alignof(Ray2f));
458 static_assert(sizeof(float)*4 == Ray2f::byte_size);
459 static_assert(sizeof(float)*4 == sizeof(Ray2f));
460
461 /**@}*/
462
463} // namespace jau::math
464
465#endif /* JAU_VEC2F_HPP_ */
Simple compound denoting a ray.
Definition vec2f.hpp:424
const value_type * const_pointer
Definition vec2f.hpp:428
Point2F< value_type > orig
Definition vec2f.hpp:440
static constexpr const size_t components
Definition vec2f.hpp:434
Vector2F< value_type > dir
Definition vec2f.hpp:443
value_type * pointer
Definition vec2f.hpp:427
static constexpr const size_t byte_size
Definition vec2f.hpp:437
static constexpr int value_alignment
Definition vec2f.hpp:431
std::string toString() const noexcept
Definition vec2f.hpp:445
Value_type value_type
Definition vec2f.hpp:426
2D vector using two value_type components.
Definition vec2f.hpp:53
const value_type * const_pointer
Definition vec2f.hpp:57
constexpr Vector2F & mul(const value_type sx, const value_type sy) noexcept
this = this * {sx, sy}, returns this.
Definition vec2f.hpp:146
static constexpr const value_type one
Definition vec2f.hpp:73
constexpr Vector2F & operator-=(const Vector2F &rhs) noexcept
this = this - rhs, returns this.
Definition vec2f.hpp:160
constexpr Vector2F & normalize() noexcept
Normalize this vector in place, returns *this.
Definition vec2f.hpp:233
constexpr Vector2F & set(const value_type vx, const value_type vy) noexcept
TODO constexpr bool operator<=>(const vec2f_t& rhs ) const noexcept { return ... }...
Definition vec2f.hpp:134
constexpr iterator begin() noexcept
Definition vec2f.hpp:114
constexpr Vector2F & add(const value_type dx, const value_type dy) noexcept
this = this + {sx, sy}, returns this.
Definition vec2f.hpp:142
Value_type value_type
Definition vec2f.hpp:55
constexpr Vector2F(Vector2F &&o) noexcept=default
constexpr_cxx26 Vector2F & rotate(const value_type radians, const Vector2F &ctr) noexcept
Rotates this vector in place, returns *this.
Definition vec2f.hpp:186
constexpr value_type length_sq() const noexcept
Return the squared length of this vector, a.k.a the squared norm or squared magnitude
Definition vec2f.hpp:221
constexpr Vector2F normal_ccw() const noexcept
Return the counter-clock-wise (CCW) normal of this vector, i.e.
Definition vec2f.hpp:310
constexpr reference operator[](size_t i) noexcept
Returns writeable reference to component.
Definition vec2f.hpp:108
constexpr value_type cross(const Vector2F &o) const noexcept
Returns cross product of this vectors and the given one, i.e.
Definition vec2f.hpp:289
constexpr_cxx26 value_type angle() const noexcept
Return the direction angle of this vector in radians.
Definition vec2f.hpp:249
constexpr iterator get(iterator xy) const noexcept
xy = this, returns xy.
Definition vec2f.hpp:117
constexpr Vector2F(const value_type x_, const value_type y_) noexcept
Definition vec2f.hpp:88
const value_type & const_reference
Definition vec2f.hpp:59
std::string toString() const noexcept
Definition vec2f.hpp:212
constexpr Vector2F & rotate(const value_type sin, const value_type cos, const Vector2F &ctr) noexcept
Rotates this vector in place, returns *this.
Definition vec2f.hpp:191
constexpr Vector2F() noexcept
Definition vec2f.hpp:82
constexpr Vector2F & scale(const value_type s) noexcept
this = this * s, returns this.
Definition vec2f.hpp:150
static constexpr const size_t components
Definition vec2f.hpp:67
constexpr Vector2F & operator/=(const value_type s) noexcept
Divide this vector with given scale factor.
Definition vec2f.hpp:180
constexpr Vector2F & operator+=(const Vector2F &rhs) noexcept
this = this + rhs, returns this.
Definition vec2f.hpp:154
constexpr value_type length() const noexcept
Return the length of this vector, a.k.a the norm or magnitude
Definition vec2f.hpp:228
constexpr Vector2F & rotate(const value_type sin, const value_type cos) noexcept
Rotates this vector in place, returns *this.
Definition vec2f.hpp:205
static constexpr const value_type zero
Definition vec2f.hpp:72
constexpr const_iterator cbegin() const noexcept
Definition vec2f.hpp:105
static constexpr const size_t byte_size
Definition vec2f.hpp:70
constexpr_cxx23 bool intersects(const Vector2F &o) const noexcept
Definition vec2f.hpp:314
constexpr Vector2F & operator*=(const value_type s) noexcept
Scale this vector with given scale factor.
Definition vec2f.hpp:170
constexpr Vector2F & set(const_iterator xy) noexcept
this = xy, returns this.
Definition vec2f.hpp:138
constexpr Vector2F & operator=(const Vector2F &) noexcept=default
const value_type * const_iterator
Definition vec2f.hpp:61
constexpr bool operator==(const Vector2F &rhs) const noexcept
Definition vec2f.hpp:123
constexpr value_type dot(const Vector2F &o) const noexcept
Return the dot product of this vector and the given one.
Definition vec2f.hpp:278
constexpr Vector2F & operator=(Vector2F &&) noexcept=default
constexpr_cxx26 Vector2F & rotate(const value_type radians) noexcept
Rotates this vector in place, returns *this.
Definition vec2f.hpp:200
constexpr_cxx26 value_type angle(const Vector2F &o) const noexcept
Return the angle between two vectors in radians.
Definition vec2f.hpp:303
value_type & reference
Definition vec2f.hpp:58
constexpr value_type cos_angle(const Vector2F &o) const noexcept
Return the cosines of the angle between two vectors.
Definition vec2f.hpp:296
static constexpr_cxx26 Vector2F from_length_angle(const value_type magnitude, const value_type radians) noexcept
Definition vec2f.hpp:78
constexpr value_type operator[](size_t i) const noexcept
Returns read-only component.
Definition vec2f.hpp:99
constexpr value_type dist(const Vector2F &o) const noexcept
Return the distance between this vector and the given one.
Definition vec2f.hpp:270
constexpr Vector2F copy() noexcept
Definition vec2f.hpp:96
value_type * iterator
Definition vec2f.hpp:60
static constexpr int value_alignment
Definition vec2f.hpp:64
value_type * pointer
Definition vec2f.hpp:56
constexpr Vector2F(const value_type v) noexcept
Definition vec2f.hpp:85
constexpr Vector2F(const Vector2F &o) noexcept=default
constexpr value_type dist_sq(const Vector2F &o) const noexcept
Return the squared distance between this vector and the given one.
Definition vec2f.hpp:261
constexpr bool is_zero() const noexcept
Definition vec2f.hpp:214
#define constexpr_cxx23
#define constexpr_cxx26
std::enable_if_t< std::is_floating_point_v< T >, bool > constexpr is_zero(const T &a, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if the given value is less than epsilon, w/ epsilon > 0.
constexpr Quaternion< T > operator-(const Quaternion< T > &lhs, const Quaternion< T > &rhs) noexcept
constexpr Vector2F< T > operator/(const Vector2F< T > &lhs, const T s) noexcept
Definition vec2f.hpp:363
constexpr Vector2F< T > max(const Vector2F< T > &lhs, const Vector2F< T > &rhs) noexcept
Definition vec2f.hpp:375
constexpr Vector2F< T > min(const Vector2F< T > &lhs, const Vector2F< T > &rhs) noexcept
Definition vec2f.hpp:369
Vector2F< Value_type > Point2F
Point2F alias of Vector2F.
Definition vec2f.hpp:400
Vector2F< float > Vec2f
Definition vec2f.hpp:387
constexpr Matrix4< T > operator*(const Matrix4< T > &lhs, const Matrix4< T > &rhs) noexcept
Definition mat4f.hpp:1863
Point2F< float > Point2f
Definition vec2f.hpp:402
Ray2F< float > Ray2f
Definition vec2f.hpp:454
constexpr Quaternion< T > operator+(const Quaternion< T > &lhs, const Quaternion< T > &rhs) noexcept
std::ostream & operator<<(std::ostream &out, const Matrix4< T > &v) noexcept
Definition mat4f.hpp:1881
uint8_t Value_type