jaulib v1.3.6
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
vec3f.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_VEC3F_HPP_
25#define JAU_VEC3F_HPP_
26
27#include <cmath>
28#include <cstdarg>
29#include <cassert>
30#include <limits>
31#include <string>
32#include <algorithm>
33
34#include <jau/float_math.hpp>
35
36#include <initializer_list>
37#include <iostream>
38
39#include <jau/math/vec2f.hpp>
40
41namespace jau::math {
42
43 /** \addtogroup Math
44 *
45 * @{
46 */
47
48 /**
49 * 3D vector using three value_type components.
50 *
51 * Component and overall alignment is natural as sizeof(value_type),
52 * i.e. sizeof(value_type) == alignof(value_type)
53 */
54 template <typename Value_type,
55 std::enable_if_t<std::is_floating_point_v<Value_type> &&
56 sizeof(Value_type) == alignof(Value_type), bool> = true>
57 class alignas(sizeof(Value_type)) Vector3F {
58 public:
61 typedef const value_type* const_pointer;
65 typedef const value_type* const_iterator;
66
67 /** value alignment is sizeof(value_type) */
68 constexpr static int value_alignment = sizeof(value_type);
69
70 /** Number of value_type components */
71 constexpr static const size_t components = 3;
72
73 /** Size in bytes with value_alignment */
74 constexpr static const size_t byte_size = components * sizeof(value_type);
75
77
78 constexpr static const value_type zero = value_type(0);
79 constexpr static const value_type one = value_type(1);
80
84
85 constexpr Vector3F() noexcept
86 : x(zero), y(zero), z(zero) {}
87
88 constexpr Vector3F(const value_type v) noexcept
89 : x(v), y(v), z(v) {}
90
91 constexpr Vector3F(const value_type x_, const value_type y_, const value_type z_) noexcept
92 : x(x_), y(y_), z(z_) {}
93
94 constexpr Vector3F(const Vec2& o2, const value_type z_) noexcept
95 : x(o2.x), y(o2.y), z(z_) {}
96
97 constexpr Vector3F(const_iterator v) noexcept
98 : x(v[0]), y(v[1]), z(v[2]) {}
99
100 constexpr Vector3F(std::initializer_list<value_type> v) noexcept
101 : x(v[0]), y(v[1]), z(v[2]) {}
102
103 constexpr Vector3F(const Vector3F& o) noexcept = default;
104 constexpr Vector3F(Vector3F&& o) noexcept = default;
105 constexpr Vector3F& operator=(const Vector3F&) noexcept = default;
106 constexpr Vector3F& operator=(Vector3F&&) noexcept = default;
107
108 constexpr Vector3F copy() noexcept { return Vector3F(*this); }
109
110 /** Returns read-only component */
111 constexpr value_type operator[](size_t i) const noexcept {
112 assert(i < 3);
113 return (&x)[i];
114 }
115
116 explicit operator const_pointer() const noexcept { return &x; }
117 constexpr const_iterator cbegin() const noexcept { return &x; }
118
119 /** Returns writeable reference to component */
120 constexpr reference operator[](size_t i) noexcept {
121 assert(i < 3);
122 return (&x)[i];
123 }
124
125 explicit operator pointer() noexcept { return &x; }
126 constexpr iterator begin() noexcept { return &x; }
127
128 /** xyz = this, returns xyz. */
129 constexpr iterator get(iterator xyz) const noexcept
130 { xyz[0] = x; xyz[1] = y; xyz[2] = z; return xyz; }
131
132 constexpr bool equals(const Vector3F& o, const value_type epsilon=std::numeric_limits<value_type>::epsilon()) const noexcept {
133 if( this == &o ) {
134 return true;
135 } else {
136 return jau::equals(x, o.x, epsilon) &&
137 jau::equals(y, o.y, epsilon) &&
138 jau::equals(z, o.z, epsilon);
139 }
140 }
141 constexpr bool operator==(const Vector3F& rhs) const noexcept {
142 return equals(rhs);
143 }
144 /** TODO
145 constexpr bool operator<=>(const vec3f_t& rhs ) const noexcept {
146 return ...
147 } */
148
149 /** this = { o, z }, returns this. */
150 constexpr Vector3F& set(const Vec2f& o, const value_type z_) noexcept {
151 x = o.x;
152 y = o.y;
153 z = z_;
154 return *this;
155 }
156
157 constexpr Vector3F& set(const value_type vx, const value_type vy, const value_type vz) noexcept
158 { x=vx; y=vy; z=vz; return *this; }
159
160 /** this = xyz, returns this. */
161 constexpr Vector3F& set(const_iterator xyz) noexcept
162 { x=xyz[0]; y=xyz[1]; z=xyz[2]; return *this; }
163
164 /** this = this + {dx, dy, dz}, returns this. */
165 constexpr Vector3F& add(const value_type dx, const value_type dy, const value_type dz) noexcept
166 { x+=dx; y+=dy; z+=dz; return *this; }
167
168 /** this = this * {sx, sy, sz}, returns this. */
169 constexpr Vector3F& mul(const value_type sx, const value_type sy, const value_type sz) noexcept
170 { x*=sx; y*=sy; z*=sz; return *this; }
171
172 /** this = this * s, returns this. */
173 constexpr Vector3F& scale(const value_type s) noexcept
174 { x*=s; y*=s; z*=s; return *this; }
175
176 /** this = this + rhs, returns this. */
177 constexpr Vector3F& operator+=(const Vector3F& rhs ) noexcept {
178 x+=rhs.x; y+=rhs.y; z+=rhs.z;
179 return *this;
180 }
181
182 /** this = this - rhs, returns this. */
183 constexpr Vector3F& operator-=(const Vector3F& rhs ) noexcept {
184 x-=rhs.x; y-=rhs.y; z-=rhs.z;
185 return *this;
186 }
187
188 /**
189 * Scale this vector with given scale factor
190 * @param s scale factor
191 * @return this instance
192 */
193 constexpr Vector3F& operator*=(const value_type s ) noexcept {
194 x*=s; y*=s; z*=s;
195 return *this;
196 }
197
198 /**
199 * Divide this vector with given scale factor
200 * @param s scale factor
201 * @return this instance
202 */
203 constexpr Vector3F& operator/=(const value_type s ) noexcept {
204 x/=s; y/=s; z/=s;
205 return *this;
206 }
207
208 /** Rotates this vector around the Z-axis in place, returns *this */
209 constexpr_cxx26 Vector3F& rotateZ(const value_type radians) noexcept {
210 return rotateZ(std::sin(radians), std::cos(radians));
211 }
212
213 /** Rotates this vector in place, returns *this */
214 constexpr Vector3F& rotateZ(const value_type sin, const value_type cos) noexcept {
215 const value_type x0 = x;
216 x = x0 * cos - y * sin;
217 y = x0 * sin + y * cos;
218 return *this;
219 }
220
221 std::string toString() const noexcept { return std::to_string(x)+", "+std::to_string(y)+", "+std::to_string(z); }
222
223 constexpr bool is_zero() const noexcept {
224 return jau::is_zero(x) && jau::is_zero(y) && jau::is_zero(z);
225 }
226
227 /**
228 * Return the squared length of a vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
229 */
230 constexpr value_type length_sq() const noexcept {
231 return x*x + y*y + z*z;
232 }
233
234 /**
235 * Return the length of a vector, a.k.a the <i>norm</i> or <i>magnitude</i>
236 */
237 constexpr value_type length() const noexcept {
238 return std::sqrt(length_sq());
239 }
240
241 /**
242 * Normalize this vector in place
243 */
244 constexpr Vector3F& normalize() noexcept {
245 const value_type lengthSq = length_sq();
246 if ( jau::is_zero( lengthSq ) ) {
247 x = zero;
248 y = zero;
249 z = zero;
250 } else {
251 const value_type invSqr = one / std::sqrt(lengthSq);
252 x *= invSqr;
253 y *= invSqr;
254 z *= invSqr;
255 }
256 return *this;
257 }
258
259 /**
260 * Return the squared distance between this vector and the given one.
261 * <p>
262 * When comparing the relative distance between two points it is usually sufficient to compare the squared
263 * distances, thus avoiding an expensive square root operation.
264 * </p>
265 */
266 constexpr value_type dist_sq(const Vector3F& o) const noexcept {
267 const value_type dx = x - o.x;
268 const value_type dy = y - o.y;
269 const value_type dz = z - o.z;
270 return dx*dx + dy*dy + dz*dz;
271 }
272
273 /**
274 * Return the distance between this vector and the given one.
275 */
276 constexpr value_type dist(const Vector3F& o) const noexcept {
277 return std::sqrt(dist_sq(o));
278 }
279
280 /**
281 * Return the dot product of this vector and the given one
282 * @return the dot product as value_type
283 */
284 constexpr value_type dot(const Vector3F& o) const noexcept {
285 return x*o.x + y*o.y + z*o.z;
286 }
287
288 /**
289 * cross product this x b
290 * @return new resulting vector
291 */
292 constexpr Vector3F cross(const Vector3F& b) const noexcept {
293 return Vector3F( y * b.z - z * b.y,
294 z * b.x - x * b.z,
295 x * b.y - y * b.x);
296 }
297
298 /**
299 * cross product this = a x b, with a, b different from this
300 * @return this for chaining
301 */
302 constexpr Vector3F& cross(const Vector3F& a, const Vector3F& b) noexcept {
303 x = a.y * b.z - a.z * b.y;
304 y = a.z * b.x - a.x * b.z;
305 z = a.x * b.y - a.y * b.x;
306 return *this;
307 }
308
309 /**
310 * Return the cosines of the angle between to vectors
311 * @param vec1 vector 1
312 * @param vec2 vector 2
313 */
314 constexpr value_type cos_angle(const Vector3F& o) const noexcept {
315 return dot(o) / ( length() * o.length() ) ;
316 }
317
318 /**
319 * Return the angle between to vectors in radians
320 * @param vec1 vector 1
321 * @param vec2 vector 2
322 */
323 constexpr_cxx26 value_type angle(const Vector3F& o) const noexcept {
324 return std::acos( cos_angle(o) );
325 }
326
327 constexpr_cxx23 bool intersects(const Vector3F& o) const noexcept {
328 const value_type eps = std::numeric_limits<value_type>::epsilon();
329 if( std::abs(x-o.x) >= eps || std::abs(y-o.y) >= eps || std::abs(z-o.z) >= eps ) {
330 return false;
331 }
332 return true;
333 }
334 };
335
336 template<typename T,
337 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
338 constexpr Vector3F<T> operator+(const Vector3F<T>& lhs, const Vector3F<T>& rhs ) noexcept {
339 // Returning a Vector3 object from the returned reference of operator+=()
340 // may hinder copy-elision or "named return value optimization" (NRVO).
341 // return Vector3<T>(lhs) += rhs;
342
343 // Returning named object allows copy-elision (NRVO),
344 // only one object is created 'on target'.
345 Vector3F<T> r(lhs); r += rhs; return r;
346 }
347
348 template<typename T,
349 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
350 constexpr Vector3F<T> operator-(const Vector3F<T>& lhs, const Vector3F<T>& rhs ) noexcept {
351 Vector3F<T> r(lhs); r -= rhs; return r;
352 }
353
354 template<typename T,
355 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
356 constexpr Vector3F<T> operator-(const Vector3F<T>& lhs) noexcept {
357 Vector3F<T> r(lhs);
358 r *= -1;
359 return r;
360 }
361
362 template<typename T,
363 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
364 constexpr Vector3F<T> operator*(const Vector3F<T>& lhs, const T s ) noexcept {
365 Vector3F<T> r(lhs); r *= s; return r;
366 }
367
368 template<typename T,
369 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
370 constexpr Vector3F<T> operator*(const T s, const Vector3F<T>& rhs) noexcept {
371 Vector3F<T> r(rhs); r *= s; return r;
372 }
373
374 template<typename T,
375 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
376 constexpr Vector3F<T> operator/(const Vector3F<T>& lhs, const T s ) noexcept {
377 Vector3F<T> r(lhs); r /= s; return r;
378 }
379
380 template<typename T,
381 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
382 constexpr Vector3F<T> min(const Vector3F<T>& lhs, const Vector3F<T>& rhs) noexcept {
383 return Vector3F<T>(std::min(lhs.x, rhs.x), std::min(lhs.y, rhs.y), std::min(lhs.z, rhs.z));
384 }
385
386 template<typename T,
387 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
388 constexpr Vector3F<T> max(const Vector3F<T>& lhs, const Vector3F<T>& rhs) noexcept {
389 return Vector3F<T>(std::max(lhs.x, rhs.x), std::max(lhs.y, rhs.y), std::max(lhs.z, rhs.z));
390 }
391
392 template<typename T,
393 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
394 std::ostream& operator<<(std::ostream& out, const Vector3F<T>& v) noexcept {
395 return out << v.toString();
396 }
397
398 static_assert(3 == Vector3F<double>::components);
399 static_assert(sizeof(double) == Vector3F<double>::value_alignment);
400 static_assert(sizeof(double) == alignof(Vector3F<double>));
401 static_assert(sizeof(double)*3 == Vector3F<double>::byte_size);
402 static_assert(sizeof(double)*3 == sizeof(Vector3F<double>));
403
405 static_assert(3 == Vec3f::components);
406 static_assert(sizeof(float) == Vec3f::value_alignment);
407 static_assert(sizeof(float) == alignof(Vec3f));
408 static_assert(sizeof(float)*3 == Vec3f::byte_size);
409 static_assert(sizeof(float)*3 == sizeof(Vec3f));
410
411 /**
412 * Point3F alias of Vector3F
413 */
414 template<typename Value_type,
415 std::enable_if_t<std::is_floating_point_v<Value_type> &&
416 sizeof(Value_type) == alignof(Value_type), bool> = true>
418
420 static_assert(3 == Point3f::components);
421 static_assert(sizeof(float) == Point3f::value_alignment);
422 static_assert(sizeof(float) == alignof(Point3f));
423 static_assert(sizeof(float)*3 == Point3f::byte_size);
424 static_assert(sizeof(float)*3 == sizeof(Point3f));
425
426 /**
427 * Simple compound denoting a ray.
428 *
429 * Component and overall alignment is as sizeof(value_type), i.e. packed.
430 *
431 * A ray, also known as a half line, consists out of it's <i>origin</i>
432 * and <i>direction</i>. Hence it is bound to only the <i>origin</i> side,
433 * where the other end is +infinitive.
434 * <pre>
435 * R(t) = R0 + Rd * t with R0 origin, Rd direction and t > 0.0
436 * </pre>
437 */
438 template<typename Value_type,
439 std::enable_if_t<std::is_floating_point_v<Value_type>, bool> = true>
440 class alignas(sizeof(Value_type)) Ray3F {
441 public:
444 typedef const value_type* const_pointer;
445
446 /** value alignment is sizeof(value_type) */
447 constexpr static int value_alignment = sizeof(value_type);
448
449 /** Number of value_type components */
450 constexpr static const size_t components = 6;
451
452 /** Size in bytes with value_alignment */
453 constexpr static const size_t byte_size = components * sizeof(value_type);
454
455 /** Origin of Ray. */
457
458 /** Normalized direction vector of ray. */
460
461 std::string toString() const noexcept { return "Ray[orig "+orig.toString()+", dir "+dir.toString() +"]"; }
462 };
463
464 template<typename T,
465 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
466 std::ostream& operator<<(std::ostream& out, const Ray3F<T>& v) noexcept {
467 return out << v.toString();
468 }
469
471 static_assert(6 == Ray3f::components);
472 static_assert(sizeof(float) == Ray3f::value_alignment);
473 static_assert(sizeof(float) == alignof(Ray3f));
474 static_assert(sizeof(float)*6 == Ray3f::byte_size);
475 static_assert(sizeof(float)*6 == sizeof(Ray3f));
476
477 /**@}*/
478
479} // namespace jau::math
480
481#endif /* JAU_VEC3F_HPP_ */
Simple compound denoting a ray.
Definition vec3f.hpp:440
std::string toString() const noexcept
Definition vec3f.hpp:461
2D vector using two value_type components.
Definition vec2f.hpp:53
3D vector using three value_type components.
Definition vec3f.hpp:57
constexpr Vector3F(const value_type v) noexcept
Definition vec3f.hpp:88
constexpr reference operator[](size_t i) noexcept
Returns writeable reference to component.
Definition vec3f.hpp:120
constexpr Vector3F & cross(const Vector3F &a, const Vector3F &b) noexcept
cross product this = a x b, with a, b different from this
Definition vec3f.hpp:302
constexpr Vector3F() noexcept
Definition vec3f.hpp:85
constexpr_cxx26 Vector3F & rotateZ(const value_type radians) noexcept
Rotates this vector around the Z-axis in place, returns *this.
Definition vec3f.hpp:209
constexpr Vector3F & set(const Vec2f &o, const value_type z_) noexcept
TODO constexpr bool operator<=>(const vec3f_t& rhs ) const noexcept { return ... }...
Definition vec3f.hpp:150
constexpr bool operator==(const Vector3F &rhs) const noexcept
Definition vec3f.hpp:141
constexpr Vector3F & operator/=(const value_type s) noexcept
Divide this vector with given scale factor.
Definition vec3f.hpp:203
constexpr_cxx26 value_type angle(const Vector3F &o) const noexcept
Return the angle between to vectors in radians.
Definition vec3f.hpp:323
constexpr Vector3F & operator=(const Vector3F &) noexcept=default
constexpr value_type cos_angle(const Vector3F &o) const noexcept
Return the cosines of the angle between to vectors.
Definition vec3f.hpp:314
constexpr Vector3F & normalize() noexcept
Normalize this vector in place.
Definition vec3f.hpp:244
constexpr Vector3F & operator=(Vector3F &&) noexcept=default
Vector2F< value_type, std::is_floating_point_v< value_type > > Vec2
Definition vec3f.hpp:76
constexpr value_type operator[](size_t i) const noexcept
Returns read-only component.
Definition vec3f.hpp:111
constexpr Vector3F(const_iterator v) noexcept
Definition vec3f.hpp:97
constexpr Vector3F & operator-=(const Vector3F &rhs) noexcept
this = this - rhs, returns this.
Definition vec3f.hpp:183
constexpr_cxx23 bool intersects(const Vector3F &o) const noexcept
Definition vec3f.hpp:327
constexpr iterator get(iterator xyz) const noexcept
xyz = this, returns xyz.
Definition vec3f.hpp:129
constexpr Vector3F & set(const value_type vx, const value_type vy, const value_type vz) noexcept
Definition vec3f.hpp:157
constexpr value_type length() const noexcept
Return the length of a vector, a.k.a the norm or magnitude
Definition vec3f.hpp:237
constexpr Vector3F & scale(const value_type s) noexcept
this = this * s, returns this.
Definition vec3f.hpp:173
constexpr value_type dist(const Vector3F &o) const noexcept
Return the distance between this vector and the given one.
Definition vec3f.hpp:276
constexpr Vector3F & mul(const value_type sx, const value_type sy, const value_type sz) noexcept
this = this * {sx, sy, sz}, returns this.
Definition vec3f.hpp:169
constexpr Vector3F & rotateZ(const value_type sin, const value_type cos) noexcept
Rotates this vector in place, returns *this.
Definition vec3f.hpp:214
constexpr Vector3F & operator+=(const Vector3F &rhs) noexcept
this = this + rhs, returns this.
Definition vec3f.hpp:177
constexpr value_type dist_sq(const Vector3F &o) const noexcept
Return the squared distance between this vector and the given one.
Definition vec3f.hpp:266
constexpr Vector3F(std::initializer_list< value_type > v) noexcept
Definition vec3f.hpp:100
constexpr Vector3F(const Vec2 &o2, const value_type z_) noexcept
Definition vec3f.hpp:94
constexpr Vector3F & add(const value_type dx, const value_type dy, const value_type dz) noexcept
this = this + {dx, dy, dz}, returns this.
Definition vec3f.hpp:165
constexpr const_iterator cbegin() const noexcept
Definition vec3f.hpp:117
constexpr bool is_zero() const noexcept
Definition vec3f.hpp:223
constexpr value_type dot(const Vector3F &o) const noexcept
Return the dot product of this vector and the given one.
Definition vec3f.hpp:284
constexpr value_type length_sq() const noexcept
Return the squared length of a vector, a.k.a the squared norm or squared magnitude
Definition vec3f.hpp:230
constexpr Vector3F(const Vector3F &o) noexcept=default
constexpr Vector3F cross(const Vector3F &b) const noexcept
cross product this x b
Definition vec3f.hpp:292
constexpr Vector3F & set(const_iterator xyz) noexcept
this = xyz, returns this.
Definition vec3f.hpp:161
constexpr Vector3F(const value_type x_, const value_type y_, const value_type z_) noexcept
Definition vec3f.hpp:91
constexpr Vector3F & operator*=(const value_type s) noexcept
Scale this vector with given scale factor.
Definition vec3f.hpp:193
constexpr Vector3F(Vector3F &&o) noexcept=default
constexpr iterator begin() noexcept
Definition vec3f.hpp:126
std::string toString() const noexcept
Definition vec3f.hpp:221
constexpr bool equals(const Vector3F &o, const value_type epsilon=std::numeric_limits< value_type >::epsilon()) const noexcept
Definition vec3f.hpp:132
#define constexpr_cxx23
#define constexpr_cxx26
std::enable_if_t< std::is_floating_point_v< T >, bool > constexpr equals(const T &a, const T &b, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if both values are equal, i.e.
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.
Vector3F< Value_type > Point3F
Point3F alias of Vector3F.
Definition vec3f.hpp:417
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
Ray3F< float > Ray3f
Definition vec3f.hpp:470
Vector2F< float > Vec2f
Definition vec2f.hpp:387
constexpr Matrix4< T > operator*(const Matrix4< T > &lhs, const Matrix4< T > &rhs) noexcept
Definition mat4f.hpp:1863
Vector3F< float > Vec3f
Definition vec3f.hpp:404
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
Point3F< float > Point3f
Definition vec3f.hpp:419
uint8_t Value_type