Gamp v0.0.7-36-g24b1eb6
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
mat4f.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this file,
9 * you can obtain one at https://opensource.org/license/mit/.
10 */
11
12#ifndef JAU_MATH_MAT4f_HPP_
13#define JAU_MATH_MAT4f_HPP_
14
15#include <cmath>
16#include <cstdarg>
17#include <cassert>
18#include <limits>
19#include <string>
20#include <vector>
21#include <initializer_list>
22#include <iostream>
23
24#include <jau/debug.hpp>
25#include <jau/float_math.hpp>
27#include <jau/math/vec3f.hpp>
28#include <jau/math/vec4f.hpp>
29#include <jau/math/recti.hpp>
31#include <jau/int_types.hpp>
32
33namespace jau::math::geom {
34 class Frustum; // forward
35}
36
37namespace jau::math {
38
39 /** \addtogroup Math
40 *
41 * @{
42 */
43
44 template<typename Value_type,
45 std::enable_if_t<std::is_floating_point_v<Value_type>, bool> >
46 class Quaternion; // forward
47
48/**
49 * Basic 4x4 value_type matrix implementation using fields for intensive use-cases (host operations).
50 * <p>
51 * Implementation covers {@link FloatUtil} matrix functionality, exposed in an object oriented manner.
52 * </p>
53 * <p>
54 * Unlike {@link com.jogamp.math.util.PMVmat4f PMVmat4f}, this class only represents one single matrix.
55 * </p>
56 * <p>
57 * For array operations the layout is expected in column-major order
58 * matching OpenGL's implementation, illustration:
59 * <pre>
60 Row-Major Column-Major (OpenGL):
61
62 | 0 1 2 tx |
63 | |
64 | 4 5 6 ty |
65 M = | |
66 | 8 9 10 tz |
67 | |
68 | 12 13 14 15 |
69
70 R C R C
71 m[0*4+3] = tx; m[0+4*3] = tx;
72 m[1*4+3] = ty; m[1+4*3] = ty;
73 m[2*4+3] = tz; m[2+4*3] = tz;
74
75 RC (std subscript order) RC (std subscript order)
76 m03 = tx; m03 = tx;
77 m13 = ty; m13 = ty;
78 m23 = tz; m23 = tz;
79
80 * </pre>
81 * </p>
82 * <p>
83 * <ul>
84 * <li><a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html">Matrix-FAQ</a></li>
85 * <li><a href="https://en.wikipedia.org/wiki/Matrix_%28mathematics%29">Wikipedia-Matrix</a></li>
86 * <li><a href="http://www.euclideanspace.com/maths/algebra/matrix/index.htm">euclideanspace.com-Matrix</a></li>
87 * </ul>
88 * </p>
89 * <p>
90 * Implementation utilizes unrolling of small vertices and matrices wherever possible
91 * while trying to access memory in a linear fashion for performance reasons, see:
92 * <ul>
93 * <li><a href="https://lessthanoptimal.github.io/Java-Matrix-Benchmark/">java-matrix-benchmark</a></li>
94 * <li><a href="https://github.com/lessthanoptimal/ejml">EJML Efficient Java Matrix Library</a></li>
95 * </ul>
96 * </p>
97 */
98
99template<typename Value_type,
100 std::enable_if_t<std::is_floating_point_v<Value_type>, bool> = true>
101class alignas(Value_type) Matrix4 {
102 public:
105 typedef const value_type* const_pointer;
110
115
116 constexpr static const value_type zero = value_type(0);
117 constexpr static const value_type one = value_type(1);
118 constexpr static const value_type two = value_type(2);
119 constexpr static const value_type half = one/two;
120
121 /**
122 * Inversion Epsilon, used with equals method to determine if two inverted matrices are close enough to be considered equal.
123 * <p>
124 * Using {@value}, which is ~84 times `std::numeric_limits<value_type>::epsilon()`.
125 * </p>
126 */
127 constexpr static const value_type inv_deviation = value_type(84) * std::numeric_limits<value_type>::epsilon(); // 84 * EPSILON(1.1920929E-7f) = 1.0E-5f
128
129 private:
130 // RC
131 value_type m00, m10, m20, m30; // column 0
132 value_type m01, m11, m21, m31; // column 1
133 value_type m02, m12, m22, m32; // column 2
134 value_type m03, m13, m23, m33; // column 3
135
136 friend geom::Frustum;
137 friend Quat;
138
139 public:
140
141 /**
142 * Creates a new identity matrix.
143 */
144 constexpr Matrix4() noexcept
145 : m00(one), m10(zero), m20(zero), m30(zero),
146 m01(zero), m11(one), m21(zero), m31(zero),
147 m02(zero), m12(zero), m22(one), m32(zero),
148 m03(zero), m13(zero), m23(zero), m33(one)
149 { }
150
151 /**
152 * Creates a new matrix based on given value_type[4*4] column major order.
153 * @param m 4x4 matrix in column-major order
154 */
155 constexpr Matrix4(const_iterator m) noexcept
156 : m00(*m), m10(*(++m)), m20(*(++m)), m30(*(++m)), // column 0
157 m01(*(++m)), m11(*(++m)), m21(*(++m)), m31(*(++m)), // column 1
158 m02(*(++m)), m12(*(++m)), m22(*(++m)), m32(*(++m)), // column 2
159 m03(*(++m)), m13(*(++m)), m23(*(++m)), m33(*(++m)) // column 3
160 {}
161
162 /**
163 * Creates a new matrix based on given value_type initializer list in column major order.
164 * @param m source initializer list value_type data to be copied into this new instance, implied size must be >= 16
165 */
166 constexpr Matrix4(std::initializer_list<value_type> m) noexcept
167 : Matrix4( m.begin() )
168 {
169 assert(m.size() >= 16 );
170 }
171
172 /**
173 * Creates a new matrix copying the values of the given {@code src} matrix.
174 */
175 constexpr Matrix4(const Matrix4& o) noexcept
176 : Matrix4( o.cbegin() )
177 { }
178
179 /**
180 * Copy assignment using the the values of the given {@code src} matrix.
181 */
182 constexpr Matrix4& operator=(const Matrix4& o) noexcept { return load(o); }
183
184 constexpr bool equals(const Matrix4& o, const value_type epsilon=std::numeric_limits<value_type>::epsilon()) const noexcept {
185 if( this == &o ) {
186 return true;
187 } else {
188 return jau::equals(m00, o.m00, epsilon) &&
189 jau::equals(m01, o.m01, epsilon) &&
190 jau::equals(m02, o.m02, epsilon) &&
191 jau::equals(m03, o.m03, epsilon) &&
192 jau::equals(m10, o.m10, epsilon) &&
193 jau::equals(m11, o.m11, epsilon) &&
194 jau::equals(m12, o.m12, epsilon) &&
195 jau::equals(m13, o.m13, epsilon) &&
196 jau::equals(m20, o.m20, epsilon) &&
197 jau::equals(m21, o.m21, epsilon) &&
198 jau::equals(m22, o.m22, epsilon) &&
199 jau::equals(m23, o.m23, epsilon) &&
200 jau::equals(m30, o.m30, epsilon) &&
201 jau::equals(m31, o.m31, epsilon) &&
202 jau::equals(m32, o.m32, epsilon) &&
203 jau::equals(m33, o.m33, epsilon);
204 }
205 }
206 constexpr bool operator==(const Matrix4& rhs) const noexcept { return equals(rhs); }
207
208 //
209 // Write to Matrix via set(..) or load(..)
210 //
211
212 /**
213 * Returns writable reference to the {@code i}th component of this column-major order matrix, 0 <= i < 16 w/o boundary check
214 */
215 constexpr reference operator[](size_t i) noexcept {
216 assert( i < 16 );
217 return (&m00)[i];
218 }
219
220 /** Sets the {@code i}th component of this column-major order matrix with value_type {@code v}, 0 <= i < 16 w/o boundary check*/
221 constexpr void set(const jau::nsize_t i, const value_type v) noexcept {
222 assert( i < 16 );
223 (&m00)[i] = v;
224 }
225
226 explicit operator pointer() noexcept { return &m00; }
227 constexpr iterator begin() noexcept { return &m00; }
228
229 /**
230 * Set this matrix to identity.
231 * <pre>
232 Translation matrix (Column Order):
233 1 0 0 0
234 0 1 0 0
235 0 0 1 0
236 0 0 0 1
237 * </pre>
238 * @return this matrix for chaining
239 */
240 constexpr Matrix4& loadIdentity() noexcept {
241 m00 = m11 = m22 = m33 = one;
242 m01 = m02 = m03 =
243 m10 = m12 = m13 =
244 m20 = m21 = m23 =
245 m30 = m31 = m32 = zero;
246 return *this;
247 }
248
249 /**
250 * Load the values of the given matrix {@code src} to this matrix w/o boundary check.
251 * @param src 4x4 matrix value_type[16] in column-major order
252 * @return this matrix for chaining
253 */
254 constexpr Matrix4& load(const_iterator src) noexcept {
255 // RC
256 m00 = *src; // column 0
257 m10 = *(++src);
258 m20 = *(++src);
259 m30 = *(++src);
260 m01 = *(++src); // column 1
261 m11 = *(++src);
262 m21 = *(++src);
263 m31 = *(++src);
264 m02 = *(++src); // column 2
265 m12 = *(++src);
266 m22 = *(++src);
267 m32 = *(++src);
268 m03 = *(++src); // column 3
269 m13 = *(++src);
270 m23 = *(++src);
271 m33 = *(++src);
272 return *this;
273 }
274 /**
275 * Load the values of the given matrix {@code src} to this matrix w/o boundary check
276 * @param src the source values
277 * @return this matrix for chaining
278 */
279 constexpr Matrix4& load(const Matrix4& src) noexcept {
280 return load( src.cbegin() );
281 }
282
283 //
284 // Read out Matrix via get(..)
285 //
286
287 /**
288 * Returns read-only {@code i}th component of the given column-major order matrix, 0 <= i < 16 w/o boundary check
289 */
290 constexpr value_type operator[](size_t i) const noexcept {
291 assert( i < 16 );
292 return (&m00)[i];
293 }
294
295 /** Returns the {@code i}th component of the given column-major order matrix, 0 <= i < 16, w/o boundary check */
296 constexpr value_type get(const jau::nsize_t i) const noexcept {
297 assert( i < 16 );
298 return (&m00)[i];
299 }
300
301 explicit operator const_pointer() const noexcept { return &m00; }
302 constexpr const_iterator cbegin() const noexcept { return &m00; }
303
304 /**
305 * Get the named column of the given column-major matrix to v_out w/o boundary check.
306 * @param column named column to copy
307 * @param v_out the column-vector storage
308 * @return given result vector <i>v_out</i> for chaining
309 */
310 constexpr Vec4& getColumn(const jau::nsize_t column, Vec4& v_out) const noexcept {
311 assert( column < 4 );
312 return v_out.set( get(0+column*4),
313 get(1+column*4),
314 get(2+column*4),
315 get(3+column*4) );
316 }
317
318 /**
319 * Get the named column of the given column-major matrix to v_out w/o boundary check.
320 * @param column named column to copy
321 * @return result vector holding the requested column
322 */
323 constexpr Vec4 getColumn(const jau::nsize_t column) const noexcept {
324 assert( column < 4 );
325 return Vec4( get(0+column*4),
326 get(1+column*4),
327 get(2+column*4),
328 get(3+column*4) );
329 }
330
331 /**
332 * Get the named column of the given column-major matrix to v_out w/o boundary check.
333 * @param column named column to copy
334 * @param v_out the column-vector storage
335 * @return given result vector <i>v_out</i> for chaining
336 */
337 constexpr Vec3& getColumn(const jau::nsize_t column, Vec3& v_out) const noexcept {
338 return v_out.set( get(0+column*4),
339 get(1+column*4),
340 get(2+column*4) );
341 }
342
343 /**
344 * Get the named row of the given column-major matrix to v_out w/ boundary check.
345 * @param row named row to copy
346 * @param v_out the row-vector storage
347 * @return given result vector <i>v_out</i> for chaining
348 */
349 constexpr Vec4& getRow(const jau::nsize_t row, Vec4& v_out) const noexcept {
350 using namespace jau::int_literals;
351 return v_out.set( get( row + 0*4_unz),
352 get( row + 1*4_unz),
353 get( row + 2*4_unz),
354 get( row + 3*4_unz) );
355 }
356 /**
357 * Get the named column of the given column-major matrix to v_out w/o boundary check.
358 * @param row named row to copy
359 * @return result vector holding the requested row
360 */
361 constexpr Vec4 getRow(const jau::nsize_t row) const noexcept {
362 using namespace jau::int_literals;
363 return Vec4( get(row+0*4_unz),
364 get(row+1*4_unz),
365 get(row+2*4_unz),
366 get(row+3*4_unz) );
367 }
368
369 /**
370 * Get the named row of the given column-major matrix to v_out w/o boundary check.
371 * @param row named row to copy
372 * @param v_out the row-vector assert( i < 16 )e
373 * @return given result vector <i>v_out</i> for chaining
374 */
375 constexpr Vec3& getRow(const jau::nsize_t row, Vec3& v_out) const noexcept {
376 using namespace jau::int_literals;
377 assert( row <= 2 );
378 return v_out.set( get(row+0*4_unz),
379 get(row+1*4_unz),
380 get(row+2*4_unz) );
381 }
382
383 /**
384 * Get this matrix into the given value_type[16] array in column major order w/o boundary check.
385 *
386 * @param dst value_type[16] array storage in column major order
387 * @return {@code dst} for chaining
388 */
389 constexpr iterator get(iterator dst) const noexcept {
390 iterator dst_i = dst;
391 *dst_i = m00; // column 0
392 *(++dst_i) = m10;
393 *(++dst_i) = m20;
394 *(++dst_i) = m30;
395 *(++dst_i) = m01; // column 1
396 *(++dst_i) = m11;
397 *(++dst_i) = m21;
398 *(++dst_i) = m31;
399 *(++dst_i) = m02; // column 2
400 *(++dst_i) = m12;
401 *(++dst_i) = m22;
402 *(++dst_i) = m32;
403 *(++dst_i) = m03; // column 3
404 *(++dst_i) = m13;
405 *(++dst_i) = m23;
406 *(++dst_i) = m33;
407 return dst;
408 }
409
410 /**
411 * Get this matrix into the given {@link FloatBuffer} in column major order.
412 *
413 * @param dst 4x4 matrix std::vector in column-major order starting at {@code dst_off}
414 * @param dst_off offset for matrix {@code dst}
415 * @return {@code dst} for chaining
416 */
417 constexpr std::vector<value_type>& get(std::vector<value_type>& dst, size_t dst_off) const noexcept {
418 assert( dst.size() >= dst_off+16 && dst_off <= std::numeric_limits<size_t>::max() - 15 );
419 get( &dst[dst_off++] );
420 return dst;
421 }
422
423 //
424 // Basic matrix operations
425 //
426
427 /**
428 * Returns the determinant of this matrix
429 * @return the matrix determinant
430 */
431 value_type determinant() const noexcept {
432 value_type ret = 0;
433 ret += m00 * ( + m11*(m22*m33 - m23*m32) - m12*(m21*m33 - m23*m31) + m13*(m21*m32 - m22*m31));
434 ret -= m01 * ( + m10*(m22*m33 - m23*m32) - m12*(m20*m33 - m23*m30) + m13*(m20*m32 - m22*m30));
435 ret += m02 * ( + m10*(m21*m33 - m23*m31) - m11*(m20*m33 - m23*m30) + m13*(m20*m31 - m21*m30));
436 ret -= m03 * ( + m10*(m21*m32 - m22*m31) - m11*(m20*m32 - m22*m30) + m12*(m20*m31 - m21*m30));
437 return ret;
438 }
439
440 /**
441 * Transpose this matrix.
442 *
443 * @return this matrix for chaining
444 */
445 Matrix4& transpose() noexcept {
446 value_type tmp;
447
448 tmp = m10;
449 m10 = m01;
450 m01 = tmp;
451
452 tmp = m20;
453 m20 = m02;
454 m02 = tmp;
455
456 tmp = m30;
457 m30 = m03;
458 m03 = tmp;
459
460 tmp = m21;
461 m21 = m12;
462 m12 = tmp;
463
464 tmp = m31;
465 m31 = m13;
466 m13 = tmp;
467
468 tmp = m32;
469 m32 = m23;
470 m23 = tmp;
471
472 return *this;
473 }
474
475 /**
476 * Transpose the given {@code src} matrix into this matrix.
477 *
478 * @param src source 4x4 matrix
479 * @return this matrix (result) for chaining
480 */
481 Matrix4& transpose(const Matrix4& src) noexcept {
482 if( &src == this ) {
483 return transpose();
484 }
485 m00 = src.m00;
486 m10 = src.m01;
487 m20 = src.m02;
488 m30 = src.m03;
489
490 m01 = src.m10;
491 m11 = src.m11;
492 m21 = src.m12;
493 m31 = src.m13;
494
495 m02 = src.m20;
496 m12 = src.m21;
497 m22 = src.m22;
498 m32 = src.m23;
499
500 m03 = src.m30;
501 m13 = src.m31;
502 m23 = src.m32;
503 m33 = src.m33;
504 return *this;
505 }
506
507 /**
508 * Invert this matrix.
509 * @return false if this matrix is singular and inversion not possible, otherwise true
510 */
511 bool invert() noexcept {
512 const value_type amax = absMax();
513 if( zero == amax ) {
514 DBG_PRINT("Matrix4:invert: absMax==0: %s", toString().c_str());
515 return false;
516 }
517 const value_type scale = one/amax;
518 const value_type a00 = m00*scale;
519 const value_type a10 = m10*scale;
520 const value_type a20 = m20*scale;
521 const value_type a30 = m30*scale;
522
523 const value_type a01 = m01*scale;
524 const value_type a11 = m11*scale;
525 const value_type a21 = m21*scale;
526 const value_type a31 = m31*scale;
527
528 const value_type a02 = m02*scale;
529 const value_type a12 = m12*scale;
530 const value_type a22 = m22*scale;
531 const value_type a32 = m32*scale;
532
533 const value_type a03 = m03*scale;
534 const value_type a13 = m13*scale;
535 const value_type a23 = m23*scale;
536 const value_type a33 = m33*scale;
537
538 const value_type b00 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31);
539 const value_type b01 = -( + a10*(a22*a33 - a23*a32) - a12*(a20*a33 - a23*a30) + a13*(a20*a32 - a22*a30));
540 const value_type b02 = + a10*(a21*a33 - a23*a31) - a11*(a20*a33 - a23*a30) + a13*(a20*a31 - a21*a30);
541 const value_type b03 = -( + a10*(a21*a32 - a22*a31) - a11*(a20*a32 - a22*a30) + a12*(a20*a31 - a21*a30));
542
543 const value_type b10 = -( + a01*(a22*a33 - a23*a32) - a02*(a21*a33 - a23*a31) + a03*(a21*a32 - a22*a31));
544 const value_type b11 = + a00*(a22*a33 - a23*a32) - a02*(a20*a33 - a23*a30) + a03*(a20*a32 - a22*a30);
545 const value_type b12 = -( + a00*(a21*a33 - a23*a31) - a01*(a20*a33 - a23*a30) + a03*(a20*a31 - a21*a30));
546 const value_type b13 = + a00*(a21*a32 - a22*a31) - a01*(a20*a32 - a22*a30) + a02*(a20*a31 - a21*a30);
547
548 const value_type b20 = + a01*(a12*a33 - a13*a32) - a02*(a11*a33 - a13*a31) + a03*(a11*a32 - a12*a31);
549 const value_type b21 = -( + a00*(a12*a33 - a13*a32) - a02*(a10*a33 - a13*a30) + a03*(a10*a32 - a12*a30));
550 const value_type b22 = + a00*(a11*a33 - a13*a31) - a01*(a10*a33 - a13*a30) + a03*(a10*a31 - a11*a30);
551 const value_type b23 = -( + a00*(a11*a32 - a12*a31) - a01*(a10*a32 - a12*a30) + a02*(a10*a31 - a11*a30));
552
553 const value_type b30 = -( + a01*(a12*a23 - a13*a22) - a02*(a11*a23 - a13*a21) + a03*(a11*a22 - a12*a21));
554 const value_type b31 = + a00*(a12*a23 - a13*a22) - a02*(a10*a23 - a13*a20) + a03*(a10*a22 - a12*a20);
555 const value_type b32 = -( + a00*(a11*a23 - a13*a21) - a01*(a10*a23 - a13*a20) + a03*(a10*a21 - a11*a20));
556 const value_type b33 = + a00*(a11*a22 - a12*a21) - a01*(a10*a22 - a12*a20) + a02*(a10*a21 - a11*a20);
557
558 const value_type det = (a00*b00 + a01*b01 + a02*b02 + a03*b03) / scale;
559 if( 0 == det ) {
560 DBG_PRINT("Matrix4:invert: det==0: %s", toString().c_str());
561 return false;
562 }
563 const value_type invdet = one / det;
564
565 m00 = b00 * invdet;
566 m10 = b01 * invdet;
567 m20 = b02 * invdet;
568 m30 = b03 * invdet;
569
570 m01 = b10 * invdet;
571 m11 = b11 * invdet;
572 m21 = b12 * invdet;
573 m31 = b13 * invdet;
574
575 m02 = b20 * invdet;
576 m12 = b21 * invdet;
577 m22 = b22 * invdet;
578 m32 = b23 * invdet;
579
580 m03 = b30 * invdet;
581 m13 = b31 * invdet;
582 m23 = b32 * invdet;
583 m33 = b33 * invdet;
584 return true;
585 }
586
587 /**
588 * Invert the {@code src} matrix values into this matrix
589 * @param src the source matrix, which values are to be inverted
590 * @return false if {@code src} matrix is singular and inversion not possible, otherwise true
591 */
592 bool invert(const Matrix4& src) noexcept {
593 const value_type amax = src.absMax();
594 if( zero == amax ) {
595 DBG_PRINT("Matrix4:invert(src): absMax==0: %s", src.toString().c_str());
596 return false;
597 }
598 const value_type scale = one/amax;
599 const value_type a00 = src.m00*scale;
600 const value_type a10 = src.m10*scale;
601 const value_type a20 = src.m20*scale;
602 const value_type a30 = src.m30*scale;
603
604 const value_type a01 = src.m01*scale;
605 const value_type a11 = src.m11*scale;
606 const value_type a21 = src.m21*scale;
607 const value_type a31 = src.m31*scale;
608
609 const value_type a02 = src.m02*scale;
610 const value_type a12 = src.m12*scale;
611 const value_type a22 = src.m22*scale;
612 const value_type a32 = src.m32*scale;
613
614 const value_type a03 = src.m03*scale;
615 const value_type a13 = src.m13*scale;
616 const value_type a23 = src.m23*scale;
617 const value_type a33 = src.m33*scale;
618
619 const value_type b00 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31);
620 const value_type b01 = -( + a10*(a22*a33 - a23*a32) - a12*(a20*a33 - a23*a30) + a13*(a20*a32 - a22*a30));
621 const value_type b02 = + a10*(a21*a33 - a23*a31) - a11*(a20*a33 - a23*a30) + a13*(a20*a31 - a21*a30);
622 const value_type b03 = -( + a10*(a21*a32 - a22*a31) - a11*(a20*a32 - a22*a30) + a12*(a20*a31 - a21*a30));
623
624 const value_type b10 = -( + a01*(a22*a33 - a23*a32) - a02*(a21*a33 - a23*a31) + a03*(a21*a32 - a22*a31));
625 const value_type b11 = + a00*(a22*a33 - a23*a32) - a02*(a20*a33 - a23*a30) + a03*(a20*a32 - a22*a30);
626 const value_type b12 = -( + a00*(a21*a33 - a23*a31) - a01*(a20*a33 - a23*a30) + a03*(a20*a31 - a21*a30));
627 const value_type b13 = + a00*(a21*a32 - a22*a31) - a01*(a20*a32 - a22*a30) + a02*(a20*a31 - a21*a30);
628
629 const value_type b20 = + a01*(a12*a33 - a13*a32) - a02*(a11*a33 - a13*a31) + a03*(a11*a32 - a12*a31);
630 const value_type b21 = -( + a00*(a12*a33 - a13*a32) - a02*(a10*a33 - a13*a30) + a03*(a10*a32 - a12*a30));
631 const value_type b22 = + a00*(a11*a33 - a13*a31) - a01*(a10*a33 - a13*a30) + a03*(a10*a31 - a11*a30);
632 const value_type b23 = -( + a00*(a11*a32 - a12*a31) - a01*(a10*a32 - a12*a30) + a02*(a10*a31 - a11*a30));
633
634 const value_type b30 = -( + a01*(a12*a23 - a13*a22) - a02*(a11*a23 - a13*a21) + a03*(a11*a22 - a12*a21));
635 const value_type b31 = + a00*(a12*a23 - a13*a22) - a02*(a10*a23 - a13*a20) + a03*(a10*a22 - a12*a20);
636 const value_type b32 = -( + a00*(a11*a23 - a13*a21) - a01*(a10*a23 - a13*a20) + a03*(a10*a21 - a11*a20));
637 const value_type b33 = + a00*(a11*a22 - a12*a21) - a01*(a10*a22 - a12*a20) + a02*(a10*a21 - a11*a20);
638
639 const value_type det = (a00*b00 + a01*b01 + a02*b02 + a03*b03) / scale;
640
641 if( 0 == det ) {
642 DBG_PRINT("Matrix4:invert(src): det==0: %s", src.toString().c_str());
643 return false;
644 }
645 const value_type invdet = one / det;
646
647 m00 = b00 * invdet;
648 m10 = b01 * invdet;
649 m20 = b02 * invdet;
650 m30 = b03 * invdet;
651
652 m01 = b10 * invdet;
653 m11 = b11 * invdet;
654 m21 = b12 * invdet;
655 m31 = b13 * invdet;
656
657 m02 = b20 * invdet;
658 m12 = b21 * invdet;
659 m22 = b22 * invdet;
660 m32 = b23 * invdet;
661
662 m03 = b30 * invdet;
663 m13 = b31 * invdet;
664 m23 = b32 * invdet;
665 m33 = b33 * invdet;
666 return true;
667 }
668
669 private:
670 /** Returns the maximum abs(mxy) field */
671 value_type absMax() const noexcept {
672 value_type max = std::abs(m00);
673 max = std::max(max, std::abs(m01));
674 max = std::max(max, std::abs(m02));
675 max = std::max(max, std::abs(m03));
676
677 max = std::max(max, std::abs(m10));
678 max = std::max(max, std::abs(m11));
679 max = std::max(max, std::abs(m12));
680 max = std::max(max, std::abs(m13));
681
682 max = std::max(max, std::abs(m20));
683 max = std::max(max, std::abs(m21));
684 max = std::max(max, std::abs(m22));
685 max = std::max(max, std::abs(m23));
686
687 max = std::max(max, std::abs(m30));
688 max = std::max(max, std::abs(m31));
689 max = std::max(max, std::abs(m32));
690 max = std::max(max, std::abs(m33));
691 return max;
692 }
693
694 public:
695 /**
696 * Multiply matrix with scalar: [this] = [this] x [s]
697 * @param s a scalar
698 * @return this matrix for chaining
699 */
700 constexpr Matrix4& operator*=( const value_type s ) noexcept {
701 m00 *= s; m10 *= s; m20 *= s; m30 *= s;
702 m01 *= s; m11 *= s; m21 *= s; m31 *= s;
703 m02 *= s; m12 *= s; m22 *= s; m32 *= s;
704 m03 *= s; m13 *= s; m23 *= s; m33 *= s;
705 return *this;
706 }
707
708 /**
709 * Multiply matrix: [this] = [this] x [b]
710 * @param b 4x4 matrix
711 * @return this matrix for chaining
712 * @see #mul(mat4f, mat4f)
713 */
714 constexpr Matrix4& mul(const Matrix4& b) noexcept {
715 // return mul(new mat4f(this), b); // <- roughly half speed
716 value_type ai0=m00; // row-0, m[0+0*4]
717 value_type ai1=m01;
718 value_type ai2=m02;
719 value_type ai3=m03;
720 m00 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ;
721 m01 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ;
722 m02 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ;
723 m03 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ;
724
725 ai0=m10; //row-1, m[1+0*4]
726 ai1=m11;
727 ai2=m12;
728 ai3=m13;
729 m10 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ;
730 m11 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ;
731 m12 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ;
732 m13 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ;
733
734 ai0=m20; // row-2, m[2+0*4]
735 ai1=m21;
736 ai2=m22;
737 ai3=m23;
738 m20 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ;
739 m21 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ;
740 m22 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ;
741 m23 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ;
742
743 ai0=m30; // row-3, m[3+0*4]
744 ai1=m31;
745 ai2=m32;
746 ai3=m33;
747 m30 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ;
748 m31 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ;
749 m32 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ;
750 m33 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ;
751 return *this;
752 }
753 /**
754 * Multiply matrix: [this] = [this] x [b]
755 * @param b 4x4 matrix
756 * @return this matrix for chaining
757 * @see #mul(mat4f, mat4f)
758 */
759 constexpr Matrix4& operator*=( const Matrix4& rhs ) noexcept {
760 return mul( rhs );
761 }
762
763 /**
764 * Multiply matrix: [this] = [a] x [b]
765 * @param a 4x4 matrix, can't be this matrix
766 * @param b 4x4 matrix, can't be this matrix
767 * @return this matrix for chaining
768 * @see #mul(mat4f)
769 */
770 constexpr Matrix4& mul(const Matrix4& a, const Matrix4& b) noexcept {
771 // row-0, m[0+0*4]
772 m00 = a.m00 * b.m00 + a.m01 * b.m10 + a.m02 * b.m20 + a.m03 * b.m30 ;
773 m01 = a.m00 * b.m01 + a.m01 * b.m11 + a.m02 * b.m21 + a.m03 * b.m31 ;
774 m02 = a.m00 * b.m02 + a.m01 * b.m12 + a.m02 * b.m22 + a.m03 * b.m32 ;
775 m03 = a.m00 * b.m03 + a.m01 * b.m13 + a.m02 * b.m23 + a.m03 * b.m33 ;
776
777 //row-1, m[1+0*4]
778 m10 = a.m10 * b.m00 + a.m11 * b.m10 + a.m12 * b.m20 + a.m13 * b.m30 ;
779 m11 = a.m10 * b.m01 + a.m11 * b.m11 + a.m12 * b.m21 + a.m13 * b.m31 ;
780 m12 = a.m10 * b.m02 + a.m11 * b.m12 + a.m12 * b.m22 + a.m13 * b.m32 ;
781 m13 = a.m10 * b.m03 + a.m11 * b.m13 + a.m12 * b.m23 + a.m13 * b.m33 ;
782
783 // row-2, m[2+0*4]
784 m20 = a.m20 * b.m00 + a.m21 * b.m10 + a.m22 * b.m20 + a.m23 * b.m30 ;
785 m21 = a.m20 * b.m01 + a.m21 * b.m11 + a.m22 * b.m21 + a.m23 * b.m31 ;
786 m22 = a.m20 * b.m02 + a.m21 * b.m12 + a.m22 * b.m22 + a.m23 * b.m32 ;
787 m23 = a.m20 * b.m03 + a.m21 * b.m13 + a.m22 * b.m23 + a.m23 * b.m33 ;
788
789 // row-3, m[3+0*4]
790 m30 = a.m30 * b.m00 + a.m31 * b.m10 + a.m32 * b.m20 + a.m33 * b.m30 ;
791 m31 = a.m30 * b.m01 + a.m31 * b.m11 + a.m32 * b.m21 + a.m33 * b.m31 ;
792 m32 = a.m30 * b.m02 + a.m31 * b.m12 + a.m32 * b.m22 + a.m33 * b.m32 ;
793 m33 = a.m30 * b.m03 + a.m31 * b.m13 + a.m32 * b.m23 + a.m33 * b.m33 ;
794
795 return *this;
796 }
797
798 /**
799 * @param v_in 4-component column-vector, can be v_out for in-place transformation
800 * @param v_out this x v_in
801 * @returns v_out for chaining
802 */
803 constexpr Vec4& mulVec4(const Vec4& v_in, Vec4& v_out) const noexcept {
804 // (one matrix row in column-major order) X (column vector)
805 const value_type x = v_in.x, y = v_in.y, z = v_in.z, w = v_in.w;
806 v_out.set( x * m00 + y * m01 + z * m02 + w * m03,
807 x * m10 + y * m11 + z * m12 + w * m13,
808 x * m20 + y * m21 + z * m22 + w * m23,
809 x * m30 + y * m31 + z * m32 + w * m33 );
810 return v_out;
811 }
812
813 /**
814 * Returns new Vec4, with this x v_in
815 * @param v_in 4-component column-vector
816 */
817 constexpr Vec4 operator*(const Vec4& rhs) const noexcept {
818 // (one matrix row in column-major order) X (column vector)
819 const value_type x = rhs.x, y = rhs.y, z = rhs.z, w = rhs.w;
820 return Vec4( x * m00 + y * m01 + z * m02 + w * m03,
821 x * m10 + y * m11 + z * m12 + w * m13,
822 x * m20 + y * m21 + z * m22 + w * m23,
823 x * m30 + y * m31 + z * m32 + w * m33 );
824 }
825
826 /**
827 * @param v_inout 4-component column-vector input and output, i.e. in-place transformation
828 * @returns v_inout for chaining
829 */
830 constexpr Vec4& mulVec4(Vec4& v_inout) const noexcept {
831 // (one matrix row in column-major order) X (column vector)
832 const value_type x = v_inout.x, y = v_inout.y, z = v_inout.z, w = v_inout.w;
833 v_inout.set( x * m00 + y * m01 + z * m02 + w * m03,
834 x * m10 + y * m11 + z * m12 + w * m13,
835 x * m20 + y * m21 + z * m22 + w * m23,
836 x * m30 + y * m31 + z * m32 + w * m33 );
837 return v_inout;
838 }
839
840 /**
841 * Affine 3f-vector transformation by 4x4 matrix
842 *
843 * 4x4 matrix multiplication with 3-component vector,
844 * using {@code 1} for for {@code v_in.w} and dropping {@code v_out.w},
845 * which shall be {@code 1}.
846 *
847 * @param v_in 3-component column-vector {@link vec3f}, can be v_out for in-place transformation
848 * @param v_out m_in x v_in, 3-component column-vector {@link vec3f}
849 * @returns v_out for chaining
850 */
851 constexpr Vec3& mulVec3(const Vec3& v_in, Vec3& v_out) const noexcept {
852 // (one matrix row in column-major order) X (column vector)
853 const value_type x = v_in.x, y = v_in.y, z = v_in.z;
854 v_out.set( x * m00 + y * m01 + z * m02 + one * m03,
855 x * m10 + y * m11 + z * m12 + one * m13,
856 x * m20 + y * m21 + z * m22 + one * m23 );
857 return v_out;
858 }
859 /**
860 * Returns new Vec3, with affine 3f-vector transformation by this 4x4 matrix: this x v_in
861 *
862 * 4x4 matrix multiplication with 3-component vector,
863 * using {@code 1} for for {@code v_in.w} and dropping {@code v_out.w},
864 * which shall be {@code 1}.
865 *
866 * @param v_in 3-component column-vector {@link vec3f}
867 */
868 constexpr Vec3 operator*(const Vec3& rhs) const noexcept {
869 // (one matrix row in column-major order) X (column vector)
870 const value_type x = rhs.x, y = rhs.y, z = rhs.z;
871 return Vec3( x * m00 + y * m01 + z * m02 + one * m03,
872 x * m10 + y * m11 + z * m12 + one * m13,
873 x * m20 + y * m21 + z * m22 + one * m23 );
874 }
875
876 /**
877 * Affine 3f-vector transformation by 4x4 matrix: v_inout = this * v_inout
878 *
879 * 4x4 matrix multiplication with 3-component vector,
880 * using {@code 1} for for {@code v_inout.w} and dropping {@code v_inout.w},
881 * which shall be {@code 1}.
882 *
883 * @param v_inout 3-component column-vector {@link vec3f} input and output, i.e. in-place transformation
884 * @returns v_inout for chaining
885 */
886 constexpr Vec3& mulVec3(Vec3& v_inout) const noexcept {
887 // (one matrix row in column-major order) X (column vector)
888 const value_type x = v_inout.x, y = v_inout.y, z = v_inout.z;
889 v_inout.set( x * m00 + y * m01 + z * m02 + one * m03,
890 x * m10 + y * m11 + z * m12 + one * m13,
891 x * m20 + y * m21 + z * m22 + one * m23 );
892 return v_inout;
893 }
894
895 //
896 // Matrix setTo...(), affine + basic
897 //
898
899 /**
900 * Set this matrix to translation.
901 * <pre>
902 Translation matrix (Column Order):
903 1 0 0 0
904 0 1 0 0
905 0 0 1 0
906 x y z 1
907 * </pre>
908 * @param x x-axis translate
909 * @param y y-axis translate
910 * @param z z-axis translate
911 * @return this matrix for chaining
912 */
913 constexpr Matrix4& setToTranslation(const value_type x, const value_type y, const value_type z) noexcept {
914 m00 = m11 = m22 = m33 = one;
915 m03 = x;
916 m13 = y;
917 m23 = z;
918 m01 = m02 =
919 m10 = m12 =
920 m20 = m21 =
921 m30 = m31 = m32 = zero;
922 return *this;
923 }
924
925 /**
926 * Set this matrix to translation.
927 * <pre>
928 Translation matrix (Column Order):
929 1 0 0 0
930 0 1 0 0
931 0 0 1 0
932 x y z 1
933 * </pre>
934 * @param t translate vec3f
935 * @return this matrix for chaining
936 */
937 constexpr Matrix4& setToTranslation(const Vec3& t) noexcept {
938 return setToTranslation(t.x, t.y, t.z);
939 }
940
941 /**
942 * Set this matrix to scale.
943 * <pre>
944 Scale matrix (Any Order):
945 x 0 0 0
946 0 y 0 0
947 0 0 z 0
948 0 0 0 1
949 * </pre>
950 * @param x x-axis scale
951 * @param y y-axis scale
952 * @param z z-axis scale
953 * @return this matrix for chaining
954 */
955 constexpr Matrix4& setToScale(const value_type x, const value_type y, const value_type z) noexcept {
956 m33 = one;
957 m00 = x;
958 m11 = y;
959 m22 = z;
960 m01 = m02 = m03 =
961 m10 = m12 = m13 =
962 m20 = m21 = m23 =
963 m30 = m31 = m32 = zero;
964 return *this;
965 }
966
967 /**
968 * Set this matrix to scale.
969 * <pre>
970 Scale matrix (Any Order):
971 x 0 0 0
972 0 y 0 0
973 0 0 z 0
974 0 0 0 1
975 * </pre>
976 * @param s scale vec3f
977 * @return this matrix for chaining
978 */
979 constexpr Matrix4& setToScale(const Vec3& s) noexcept {
980 return setToScale(s.x, s.y, s.z);
981 }
982
983 /**
984 * Set this matrix to rotation from the given axis and angle in radians.
985 * <pre>
986 Rotation matrix (Column Order):
987 xx(1-c)+c xy(1-c)+zs xz(1-c)-ys 0
988 xy(1-c)-zs yy(1-c)+c yz(1-c)+xs 0
989 xz(1-c)+ys yz(1-c)-xs zz(1-c)+c 0
990 0 0 0 1
991 * </pre>
992 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
993 * @param ang_rad angle in radians
994 * @param x x of rotation axis
995 * @param y y of rotation axis
996 * @param z z of rotation axis
997 * @return this matrix for chaining
998 */
1000 const value_type c = std::cos(ang_rad);
1001 const value_type ic= one - c;
1002 const value_type s = std::sin(ang_rad);
1003
1004 Vec3 tmp(x, y, z); tmp.normalize();
1005 x = tmp.x; y = tmp.y; z = tmp.z;
1006
1007 const value_type xy = x*y;
1008 const value_type xz = x*z;
1009 const value_type xs = x*s;
1010 const value_type ys = y*s;
1011 const value_type yz = y*z;
1012 const value_type zs = z*s;
1013 m00 = x*x*ic+c;
1014 m10 = xy*ic+zs;
1015 m20 = xz*ic-ys;
1016 m30 = zero;
1017
1018 m01 = xy*ic-zs;
1019 m11 = y*y*ic+c;
1020 m21 = yz*ic+xs;
1021 m31 = zero;
1022
1023 m02 = xz*ic+ys;
1024 m12 = yz*ic-xs;
1025 m22 = z*z*ic+c;
1026 m32 = zero;
1027
1028 m03 = zero;
1029 m13 = zero;
1030 m23 = zero;
1031 m33 = one;
1032
1033 return *this;
1034 }
1035
1036 /**
1037 * Set this matrix to rotation from the given axis and angle in radians.
1038 * <pre>
1039 Rotation matrix (Column Order):
1040 xx(1-c)+c xy(1-c)+zs xz(1-c)-ys 0
1041 xy(1-c)-zs yy(1-c)+c yz(1-c)+xs 0
1042 xz(1-c)+ys yz(1-c)-xs zz(1-c)+c 0
1043 0 0 0 1
1044 * </pre>
1045 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
1046 * @param ang_rad angle in radians
1047 * @param axis rotation axis
1048 * @return this matrix for chaining
1049 */
1050 constexpr_cxx26 Matrix4& setToRotationAxis(const value_type ang_rad, const Vec3& axis) noexcept {
1051 return setToRotationAxis(ang_rad, axis.x, axis.y, axis.z);
1052 }
1053
1054 /**
1055 * Set this matrix to rotation from the given Euler rotation angles in radians.
1056 * <p>
1057 * The rotations are applied in the given order:
1058 * <ul>
1059 * <li>y - heading</li>
1060 * <li>z - attitude</li>
1061 * <li>x - bank</li>
1062 * </ul>
1063 * </p>
1064 * @param bankX the Euler pitch angle in radians. (rotation about the X axis)
1065 * @param headingY the Euler yaw angle in radians. (rotation about the Y axis)
1066 * @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis)
1067 * @return this matrix for chaining
1068 * <p>
1069 * Implementation does not use Quaternion and hence is exposed to
1070 * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a>,
1071 * consider using Quaternion::toMatrix().
1072 * </p>
1073 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q36">Matrix-FAQ Q36</a>
1074 * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm">euclideanspace.com-eulerToMatrix</a>
1075 * @see Quaternion::toMatrix()
1076 */
1077 constexpr_cxx26 Matrix4& setToRotationEuler(const value_type bankX, const value_type headingY, const value_type attitudeZ) noexcept {
1078 // Assuming the angles are in radians.
1079 const value_type ch = std::cos(headingY);
1080 const value_type sh = std::sin(headingY);
1081 const value_type ca = std::cos(attitudeZ);
1082 const value_type sa = std::sin(attitudeZ);
1083 const value_type cb = std::cos(bankX);
1084 const value_type sb = std::sin(bankX);
1085
1086 m00 = ch*ca;
1087 m10 = sa;
1088 m20 = -sh*ca;
1089 m30 = zero;
1090
1091 m01 = sh*sb - ch*sa*cb;
1092 m11 = ca*cb;
1093 m21 = sh*sa*cb + ch*sb;
1094 m31 = zero;
1095
1096 m02 = ch*sa*sb + sh*cb;
1097 m12 = -ca*sb;
1098 m22 = -sh*sa*sb + ch*cb;
1099 m32 = zero;
1100
1101 m03 = zero;
1102 m13 = zero;
1103 m23 = zero;
1104 m33 = one;
1105
1106 return *this;
1107 }
1108
1109 /**
1110 * Set this matrix to rotation from the given Euler rotation angles in radians.
1111 * <p>
1112 * The rotations are applied in the given order:
1113 * <ul>
1114 * <li>y - heading</li>
1115 * <li>z - attitude</li>
1116 * <li>x - bank</li>
1117 * </ul>
1118 * </p>
1119 * @param angradXYZ euler angle vector in radians holding x-bank, y-heading and z-attitude
1120 * @return this quaternion for chaining.
1121 * <p>
1122 * Implementation does not use Quaternion and hence is exposed to
1123 * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a>,
1124 * consider using Quaternion::toMatrix().
1125 * </p>
1126 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q36">Matrix-FAQ Q36</a>
1127 * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm">euclideanspace.com-eulerToMatrix</a>
1128 * @see Quaternion::toMatrix()
1129 */
1130 constexpr_cxx26 Matrix4& setToRotationEuler(const Vec3& angradXYZ) noexcept {
1131 return setToRotationEuler(angradXYZ.x, angradXYZ.y, angradXYZ.z);
1132 }
1133
1134 /**
1135 * Set this matrix to rotation using the given Quaternion.
1136 * <p>
1137 * Implementation Details:
1138 * <ul>
1139 * <li> makes identity matrix if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
1140 * <li> The fields [m00 .. m22] define the rotation</li>
1141 * </ul>
1142 * </p>
1143 *
1144 * @param q the Quaternion representing the rotation
1145 * @return this matrix for chaining
1146 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54">Matrix-FAQ Q54</a>
1147 * @see Quaternion#toMatrix(float[])
1148 * @see #getRotation()
1149 */
1150 Matrix4& setToRotation(const Quat& q);
1151
1152 /**
1153 * Returns the rotation [m00 .. m22] fields converted to a Quaternion.
1154 * @param res resulting Quaternion
1155 * @return the resulting Quaternion for chaining.
1156 * @see Quaternion#setFromMat(float, float, float, float, float, float, float, float, float)
1157 * @see #setToRotation(Quaternion)
1158 */
1159 Quat& getRotation(Quat& res) const noexcept;
1160
1161 /**
1162 * Set this matrix to orthogonal projection.
1163 * <pre>
1164 Ortho matrix (Column Order):
1165 2/dx 0 0 0
1166 0 2/dy 0 0
1167 0 0 2/dz 0
1168 tx ty tz 1
1169 * </pre>
1170 * @param left
1171 * @param right
1172 * @param bottom
1173 * @param top
1174 * @param zNear
1175 * @param zFar
1176 * @return this matrix for chaining
1177 */
1178 constexpr Matrix4& setToOrtho(const value_type left, const value_type right,
1179 const value_type bottom, const value_type top,
1180 const value_type zNear, const value_type zFar) noexcept {
1181 {
1182 // m00 = m11 = m22 = m33 = one;
1183 m10 = m20 = m30 = zero;
1184 m01 = m21 = m31 = zero;
1185 m02 = m12 = m32 = zero;
1186 // m03 = m13 = m23 = zero;
1187 }
1188 const value_type dx=right-left;
1189 const value_type dy=top-bottom;
1190 const value_type dz=zFar-zNear;
1191 const value_type tx=-one*(right+left)/dx;
1192 const value_type ty=-one*(top+bottom)/dy;
1193 const value_type tz=-one*(zFar+zNear)/dz;
1194
1195 m00 = two/dx;
1196 m11 = two/dy;
1197 m22 = -two/dz;
1198
1199 m03 = tx;
1200 m13 = ty;
1201 m23 = tz;
1202 m33 = one;
1203
1204 return *this;
1205 }
1206
1207 /**
1208 * Set this matrix to frustum.
1209 * <pre>
1210 Frustum matrix (Column Order):
1211 2*zNear/dx 0 0 0
1212 0 2*zNear/dy 0 0
1213 A B C -1
1214 0 0 D 0
1215 * </pre>
1216 * @param left
1217 * @param right
1218 * @param bottom
1219 * @param top
1220 * @param zNear
1221 * @param zFar
1222 * @return this matrix for chaining
1223 * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear}
1224 * or {@code left == right}, or {@code bottom == top}.
1225 */
1226 Matrix4& setToFrustum(const value_type left, const value_type right,
1227 const value_type bottom, const value_type top,
1228 const value_type zNear, const value_type zFar) {
1229 if( zNear <= zero || zFar <= zNear ) {
1230 throw jau::IllegalArgumentError("Requirements zNear > 0 and zFar > zNear, but zNear "+std::to_string(zNear)+", zFar "+std::to_string(zFar), E_FILE_LINE);
1231 }
1232 if( left == right || top == bottom) {
1233 throw jau::IllegalArgumentError("GL_INVALID_VALUE: top,bottom and left,right must not be equal", E_FILE_LINE);
1234 }
1235 {
1236 // m00 = m11 = m22 = m33 = 1f;
1237 m10 = m20 = m30 = zero;
1238 m01 = m21 = m31 = zero;
1239 m03 = m13 = zero;
1240 }
1241 const value_type zNear2 = two*zNear;
1242 const value_type dx=right-left;
1243 const value_type dy=top-bottom;
1244 const value_type dz=zFar-zNear;
1245 const value_type A=(right+left)/dx;
1246 const value_type B=(top+bottom)/dy;
1247 const value_type C=-one*(zFar+zNear)/dz;
1248 const value_type D=-two*(zFar*zNear)/dz;
1249
1250 m00 = zNear2/dx;
1251 m11 = zNear2/dy;
1252
1253 m02 = A;
1254 m12 = B;
1255 m22 = C;
1256 m32 = -one;
1257
1258 m23 = D;
1259 m33 = zero;
1260
1261 return *this;
1262 }
1263
1264 /**
1265 * Set this matrix to perspective {@link #setToFrustum(value_type, value_type, value_type, value_type, value_type, value_type) frustum} projection.
1266 *
1267 * @param fovy_rad angle in radians
1268 * @param aspect aspect ratio width / height
1269 * @param zNear
1270 * @param zFar
1271 * @return this matrix for chaining
1272 * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear}
1273 * @see #setToFrustum(value_type, value_type, value_type, value_type, value_type, value_type)
1274 */
1275 Matrix4& setToPerspective(const value_type fovy_rad, const value_type aspect, const value_type zNear, const value_type zFar) {
1276 const value_type top = std::tan(fovy_rad/two) * zNear; // use tangent of half-fov !
1277 const value_type bottom = -one * top; // -1f * fovhvTan.top * zNear
1278 const value_type left = aspect * bottom; // aspect * -1f * fovhvTan.top * zNear
1279 const value_type right = aspect * top; // aspect * fovhvTan.top * zNear
1280 return setToFrustum(left, right, bottom, top, zNear, zFar);
1281 }
1282
1283 /**
1284 * Set this matrix to perspective {@link #setToFrustum(value_type, value_type, value_type, value_type, value_type, value_type) frustum} projection.
1285 *
1286 * @param fovhv {@link FovHVHalves} field of view in both directions, may not be centered, either in radians or tangent
1287 * @param zNear
1288 * @param zFar
1289 * @return this matrix for chaining
1290 * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear}
1291 * @see #setToFrustum(value_type, value_type, value_type, value_type, value_type, value_type)
1292 * @see Frustum#updateByFovDesc(mat4f, com.jogamp.math.geom.Frustum.FovDesc)
1293 */
1294 Matrix4& setToPerspective(const FovHVHalves& fovhv, const value_type zNear, const value_type zFar) {
1295 const FovHVHalves fovhvTan = fovhv.toTangents(); // use tangent of half-fov !
1296 const value_type top = fovhvTan.top * zNear;
1297 const value_type bottom = -one * fovhvTan.bottom * zNear;
1298 const value_type left = -one * fovhvTan.left * zNear;
1299 const value_type right = fovhvTan.right * zNear;
1300 return setToFrustum(left, right, bottom, top, zNear, zFar);
1301 }
1302
1303 /**
1304 * Set this matrix to the <i>look-at</i> matrix based on given parameters.
1305 * <p>
1306 * Consist out of two matrix multiplications:
1307 * <pre>
1308 * <b>R</b> = <b>L</b> x <b>T</b>,
1309 * with <b>L</b> for <i>look-at</i> matrix and
1310 * <b>T</b> for eye translation.
1311 *
1312 * Result <b>R</b> can be utilized for <i>projection or modelview</i> multiplication, i.e.
1313 * <b>M</b> = <b>M</b> x <b>R</b>,
1314 * with <b>M</b> being the <i>projection or modelview</i> matrix.
1315 * </pre>
1316 * </p>
1317 * @param eye 3 component eye vector
1318 * @param center 3 component center vector
1319 * @param up 3 component up vector
1320 * @return this matrix for chaining
1321 */
1322 constexpr Matrix4& setToLookAt(const Vec3& eye, const Vec3& center, const Vec3& up) noexcept {
1323 // normalized forward!
1324 const Vec3 fwd = ( center - eye ).normalize();
1325
1326 /* Side = forward x up, normalized */
1327 const Vec3 side = fwd.cross(up).normalize();
1328
1329 /* Recompute up as: up = side x forward */
1330 const Vec3 up2 = side.cross(fwd);
1331
1332 m00 = side.x;
1333 m10 = up2.x;
1334 m20 = -fwd.x;
1335 m30 = 0;
1336
1337 m01 = side.y;
1338 m11 = up2.y;
1339 m21 = -fwd.y;
1340 m31 = 0;
1341
1342 m02 = side.z;
1343 m12 = up2.z;
1344 m22 = -fwd.z;
1345 m32 = 0;
1346
1347 m03 = 0;
1348 m13 = 0;
1349 m23 = 0;
1350 m33 = 1;
1351
1352 Matrix4 tmp;
1353 return mul( tmp.setToTranslation( -eye.x, -eye.y, -eye.z ) );
1354 }
1355
1356 /**
1357 * Set this matrix to the <i>pick</i> matrix based on given parameters.
1358 * <p>
1359 * Traditional <code>gluPickMatrix</code> implementation.
1360 * </p>
1361 * <p>
1362 * Consist out of two matrix multiplications:
1363 * <pre>
1364 * <b>R</b> = <b>T</b> x <b>S</b>,
1365 * with <b>T</b> for viewport translation matrix and
1366 * <b>S</b> for viewport scale matrix.
1367 *
1368 * Result <b>R</b> can be utilized for <i>projection</i> multiplication, i.e.
1369 * <b>P</b> = <b>P</b> x <b>R</b>,
1370 * with <b>P</b> being the <i>projection</i> matrix.
1371 * </pre>
1372 * </p>
1373 * <p>
1374 * To effectively use the generated pick matrix for picking,
1375 * call {@link #setToPick(value_type, value_type, value_type, value_type, Recti, mat4f) setToPick(..)}
1376 * and multiply a {@link #setToPerspective(value_type, value_type, value_type, value_type) custom perspective matrix}
1377 * by this pick matrix. Then you may load the result onto the perspective matrix stack.
1378 * </p>
1379 * @param x the center x-component of a picking region in window coordinates
1380 * @param y the center y-component of a picking region in window coordinates
1381 * @param deltaX the width of the picking region in window coordinates.
1382 * @param deltaY the height of the picking region in window coordinates.
1383 * @param viewport Rect4i viewport
1384 * @return true if successful or false if either delta value is <= zero.
1385 */
1386 constexpr bool setToPick(const value_type x, const value_type y, const value_type deltaX, const value_type deltaY,
1387 const Recti& viewport) noexcept {
1388 if (deltaX <= 0 || deltaY <= 0) {
1389 return false;
1390 }
1391 /* Translate and scale the picked region to the entire window */
1392 setToTranslation( ( viewport.width() - two * ( x - viewport.x() ) ) / deltaX,
1393 ( viewport.height() - two * ( y - viewport.y() ) ) / deltaY,
1394 0);
1395 Matrix4 mat4Tmp;
1396 mat4Tmp.setToScale( viewport.width() / deltaX, viewport.height() / deltaY, one );
1397 mul(mat4Tmp);
1398 return true;
1399 }
1400
1401 //
1402 // Matrix affine operations using setTo..()
1403 //
1404
1405 /**
1406 * Rotate this matrix about give axis and angle in radians, i.e. multiply by {@link #setToRotationAxis(value_type, value_type, value_type, value_type) axis-rotation matrix}.
1407 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
1408 * @param angrad angle in radians
1409 * @param x x of rotation axis
1410 * @param y y of rotation axis
1411 * @param z z of rotation axis
1412 * @return this matrix for chaining
1413 */
1414 constexpr_cxx26 Matrix4& rotate(const value_type ang_rad, const value_type x, const value_type y, const value_type z) noexcept {
1415 Matrix4 tmp;
1416 return mul( tmp.setToRotationAxis(ang_rad, x, y, z) );
1417 }
1418
1419 /**
1420 * Rotate this matrix about give axis and angle in radians, i.e. multiply by {@link #setToRotationAxis(value_type, vec3f) axis-rotation matrix}.
1421 * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
1422 * @param angrad angle in radians
1423 * @param axis rotation axis
1424 * @return this matrix for chaining
1425 */
1426 constexpr_cxx26 Matrix4& rotate(const value_type ang_rad, const Vec3& axis) noexcept {
1427 Matrix4 tmp;
1428 return mul( tmp.setToRotationAxis(ang_rad, axis) );
1429 }
1430
1431 /**
1432 * Rotate this matrix with the given {@link Quaternion}, i.e. multiply by {@link #setToRotation(Quaternion) Quaternion's rotation matrix}.
1433 * @param tmp temporary Matrix4f used for multiplication
1434 * @return this matrix for chaining
1435 */
1436 Matrix4& rotate(const Quat& quat) noexcept;
1437
1438 /**
1439 * Translate this matrix, i.e. multiply by {@link #setToTranslation(value_type, value_type, value_type) translation matrix}.
1440 * @param x x translation
1441 * @param y y translation
1442 * @param z z translation
1443 * @return this matrix for chaining
1444 */
1445 constexpr Matrix4& translate(const value_type x, const value_type y, const value_type z) noexcept {
1446 Matrix4 tmp;
1447 return mul( tmp.setToTranslation(x, y, z) );
1448 }
1449
1450 /**
1451 * Translate this matrix, i.e. multiply by {@link #setToTranslation(vec3f) translation matrix}.
1452 * @param t translation vec3f
1453 * @return this matrix for chaining
1454 */
1455 constexpr Matrix4& translate(const Vec3& t) noexcept {
1456 Matrix4 tmp;
1457 return mul( tmp.setToTranslation(t) );
1458 }
1459
1460 /**
1461 * Scale this matrix, i.e. multiply by {@link #setToScale(value_type, value_type, value_type) scale matrix}.
1462 * @param x x scale
1463 * @param y y scale
1464 * @param z z scale
1465 * @return this matrix for chaining
1466 */
1467 constexpr Matrix4& scale(const value_type x, const value_type y, const value_type z) noexcept {
1468 Matrix4 tmp;
1469 return mul( tmp.setToScale(x, y, z) );
1470 }
1471
1472 /**
1473 * Scale this matrix, i.e. multiply by {@link #setToScale(const Vec3&) scale matrix}.
1474 * @param sxyz scale factor for each component
1475 * @return this matrix for chaining
1476 */
1477 constexpr Matrix4& scale(const Vec3& sxyz) noexcept {
1478 Matrix4 tmp;
1479 return mul( tmp.setToScale(sxyz) );
1480 }
1481
1482 /**
1483 * Scale this matrix, i.e. multiply by {@link #setToScale(value_type, value_type, value_type) scale matrix}.
1484 * @param s scale for x-, y- and z-axis
1485 * @return this matrix for chaining
1486 */
1487 constexpr Matrix4& scale(const value_type s) noexcept {
1488 Matrix4 tmp;
1489 return mul( tmp.setToScale(s, s, s) );
1490 }
1491
1492 //
1493 // Static multi Matrix ops
1494 //
1495
1496 /**
1497 * Map object coordinates to window coordinates.
1498 *
1499 * Traditional <code>gluProject</code> implementation.
1500 *
1501 * @param obj object position, 3 component vector
1502 * @param mPMv [projection] x [modelview] matrix, i.e. P x Mv
1503 * @param viewport Rect4i viewport
1504 * @param winPos 3 component window coordinate, the result
1505 * @return true if successful, otherwise false (z is 1)
1506 */
1507 static bool mapObjToWin(const Vec3& obj, const Matrix4& mPMv,
1508 const Recti& viewport, Vec3& winPos) noexcept
1509 {
1510 // rawWin = P * Mv * o = PMv * o
1511 Vec4 rawWin = mPMv * Vec4(obj, one);
1512 return mapToWinImpl(rawWin, viewport, winPos);
1513 }
1514
1515 /**
1516 * Map object coordinates to window coordinates.
1517 *
1518 * Traditional <code>gluProject</code> implementation.
1519 *
1520 * @param obj object position, 3 component vector
1521 * @param mMv modelview matrix
1522 * @param mP projection matrix
1523 * @param viewport Rect4i viewport
1524 * @param winPos 3 component window coordinate, the result
1525 * @return true if successful, otherwise false (z is 1)
1526 */
1527 static bool mapObjToWin(const Vec3& obj, const Matrix4& mMv, const Matrix4& mP,
1528 const Recti& viewport, Vec3& winPos) noexcept
1529 {
1530 Vec4 rawWin = mP * mMv * Vec4(obj, one);
1531 return mapToWinImpl(rawWin, viewport, winPos);
1532 }
1533
1534 /**
1535 * Map world coordinates ( M x object ) to window coordinates.
1536 *
1537 * @param world world position, 3 component vector
1538 * @param mV view matrix
1539 * @param mP projection matrix
1540 * @param viewport Rect4i viewport
1541 * @param winPos 3 component window coordinate, the result
1542 * @return true if successful, otherwise false (z is 1)
1543 */
1544 static bool mapWorldToWin(const Vec3& world, const Matrix4& mV, const Matrix4& mP,
1545 const Recti& viewport, Vec3& winPos) noexcept
1546 {
1547 Vec4 rawWin = mP * mV * Vec4(world, one);
1548 return mapToWinImpl(rawWin, viewport, winPos);
1549 }
1550
1551 /**
1552 * Map view coordinates ( Mv x object ) to window coordinates.
1553 *
1554 * @param view view position, 3 component vector
1555 * @param mP projection matrix
1556 * @param viewport Rect4i viewport
1557 * @param winPos 3 component window coordinate, the result
1558 * @return true if successful, otherwise false (z is 1)
1559 */
1560 static bool mapViewToWin(const Vec3& view, const Matrix4& mP,
1561 const Recti& viewport, Vec3& winPos) noexcept
1562 {
1563 Vec4 rawWin = mP * Vec4(view, one);
1564 return mapToWinImpl(rawWin, viewport, winPos);
1565 }
1566
1567 private:
1568 static bool mapToWinImpl(Vec4& rawWin,
1569 const Recti& viewport, Vec3& winPos) noexcept
1570 {
1571 if ( zero == rawWin.w ) {
1572 return false;
1573 }
1574
1575 const value_type s = ( one / rawWin.w ) * half;
1576
1577 // Map x, y and z to range 0-1 (w is ignored)
1578 rawWin.scale(s).add(half, half, half, zero);
1579
1580 // Map x,y to viewport
1581 winPos.set( rawWin.x * viewport.width() + viewport.x(),
1582 rawWin.y * viewport.height() + viewport.y(),
1583 rawWin.z );
1584
1585 return true;
1586 }
1587
1588 public:
1589 /**
1590 * Map window coordinates to object coordinates.
1591 *
1592 * Traditional <code>gluUnProject</code> implementation.
1593 *
1594 * @param winx
1595 * @param winy
1596 * @param winz
1597 * @param mMv 4x4 modelview matrix
1598 * @param mP 4x4 projection matrix
1599 * @param viewport Rect4i viewport
1600 * @param objPos 3 component object coordinate, the result
1601 * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
1602 */
1603 static bool mapWinToObj(const value_type winx, const value_type winy, const value_type winz,
1604 const Matrix4& mMv, const Matrix4& mP,
1605 const Recti& viewport,
1606 Vec3& objPos) noexcept
1607 {
1608 // invPMv = Inv(P x Mv)
1609 Matrix4 invPMv;
1610 invPMv.mul(mP, mMv);
1611 if( !invPMv.invert() ) {
1612 return false;
1613 }
1614 return mapWinToAny(winx, winy, winz, invPMv, viewport, objPos);
1615 }
1616
1617 /**
1618 * Map window coordinates to view coordinates.
1619 *
1620 * @param winx
1621 * @param winy
1622 * @param winz
1623 * @param mP 4x4 projection matrix
1624 * @param viewport Rect4i viewport
1625 * @param viewPos 3 component view coordinate, the result
1626 * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
1627 */
1628 static bool mapWinToView(const value_type winx, const value_type winy, const value_type winz,
1629 const Matrix4& mP,
1630 const Recti& viewport,
1631 Vec3& viewPos) noexcept
1632 {
1633 // invP = Inv(P)
1634 Matrix4 invP;
1635 if( !invP.invert(mP) ) {
1636 return false;
1637 }
1638 return mapWinToAny(winx, winy, winz, invP, viewport, viewPos);
1639 }
1640
1641 /**
1642 * Map window coordinates to object, world or view coordinates, depending on `invAny` argument.
1643 *
1644 * Traditional <code>gluUnProject</code> implementation.
1645 *
1646 * `invAny` maybe set as follows for
1647 * - to object: inverse(P x Mv) = `([projection] x [modelview])'`
1648 * - to world: inverse(P x V) = `([projection] x [view])'`
1649 * - to view: inverse(P) = `[projection]'`
1650 *
1651 * @param winx
1652 * @param winy
1653 * @param winz
1654 * @param invAny inverse matrix, either Inv(P x Mv) to object, Inv(P x V) to world or
1655 Inv(P) `[projection]'` to view
1656 * @param viewport Rect4i viewport
1657 * @param objPos 3 component object coordinate, the result
1658 * @return true if successful, otherwise false (can't invert matrix, or becomes infinity due to zero z)
1659 */
1660 static bool mapWinToAny(const value_type winx, const value_type winy, const value_type winz,
1661 const Matrix4& invAny,
1662 const Recti& viewport,
1663 Vec3& objPos) noexcept
1664 {
1665 Vec4 winPos(winx, winy, winz, one);
1666
1667 // Map x and y from window coordinates
1668 winPos.add(-viewport.x(), -viewport.y(), zero, zero).mul(one/viewport.width(), one/viewport.height(), one, one);
1669
1670 // Map to range -1 to 1
1671 winPos.mul(two, two, two, one).add(-one, -one, -one, zero);
1672
1673 // rawObjPos = Inv(P x Mv) * winPos
1674 Vec4 rawObjPos = invAny * winPos;
1675
1676 if ( zero == rawObjPos.w ) {
1677 return false;
1678 }
1679
1680 rawObjPos.scale(one / rawObjPos.w).getVec3(objPos);
1681 return true;
1682 }
1683
1684 /**
1685 * Map two window coordinates to two to object, world or view coordinates, depending on `invAny` argument.
1686 *
1687 * Both coordinates are distinguished by their z component.
1688 *
1689 * Traditional <code>gluUnProject</code> implementation.
1690 *
1691 * `invAny` maybe set as follows for
1692 * - to object: inverse(P x Mv) = `([projection] x [modelview])'`
1693 * - to world: inverse(P x V) = `([projection] x [view])'`
1694 * - to view: inverse(P) = `[projection]'`
1695 *
1696 * @param winx
1697 * @param winy
1698 * @param winz1
1699 * @param winz2
1700 * @param invAny inverse matrix, either Inv(P x Mv) to object, Inv(P x V) to world or
1701 Inv(P) `[projection]'` to view
1702 * @param viewport Rect4i viewport vector
1703 * @param objPos1 3 component object coordinate, the result
1704 * @return true if successful, otherwise false (can't invert matrix, or becomes infinity due to zero z)
1705 */
1706 static bool mapWinToAny(const value_type winx, const value_type winy, const value_type winz1, const value_type winz2,
1707 const Matrix4& invAny,
1708 const Recti& viewport,
1709 Vec3& objPos1, Vec3& objPos2) noexcept
1710 {
1711 Vec4 winPos(winx, winy, winz1, one);
1712
1713 // Map x and y from window coordinates
1714 winPos.add(-viewport.x(), -viewport.y(), zero, zero).mul(one/viewport.width(), one/viewport.height(), one, one);
1715
1716 // Map to range -1 to 1
1717 winPos.mul(two, two, two, one).add(-one, -one, -one, zero);
1718
1719 // rawObjPos = Inv(P x Mv) x winPos1
1720 Vec4 rawObjPos = invAny * winPos;
1721
1722 if ( zero == rawObjPos.w ) {
1723 return false;
1724 }
1725 rawObjPos.scale(one / rawObjPos.w).getVec3(objPos1);
1726
1727 //
1728 // winz2
1729 //
1730 // Map Z to range -1 to 1
1731 winPos.z = winz2 * two - one;
1732
1733 // rawObjPos = Inv(P x Mv) x winPos2
1734 invAny.mulVec4(winPos, rawObjPos);
1735
1736 if ( zero == rawObjPos.w ) {
1737 return false;
1738 }
1739 rawObjPos.scale(one / rawObjPos.w).getVec3(objPos2);
1740
1741 return true;
1742 }
1743
1744 /**
1745 * Map window coordinates to object coordinates.
1746 *
1747 * Traditional <code>gluUnProject4</code> implementation.
1748 *
1749 * @param winx
1750 * @param winy
1751 * @param winz
1752 * @param clipw
1753 * @param mMv 4x4 modelview matrix
1754 * @param mP 4x4 projection matrix
1755 * @param viewport Rect4i viewport vector
1756 * @param near
1757 * @param far
1758 * @param obj_pos 4 component object coordinate, the result
1759 * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
1760 */
1761 static bool mapWinToObj4(const value_type winx, const value_type winy, const value_type winz, const value_type clipw,
1762 const Matrix4& mMv, const Matrix4& mP,
1763 const Recti& viewport,
1764 const value_type near, const value_type far,
1765 Vec4& objPos) noexcept
1766 {
1767 // invPMv = Inv(P x Mv)
1768 Matrix4 invPMv;
1769 invPMv.mul(mP, mMv);
1770 if( !invPMv.invert() ) {
1771 return false;
1772 }
1773 return mapWinToObj4(winx, winy, winz, clipw,
1774 invPMv, viewport, near, far, objPos);
1775 }
1776
1777 /**
1778 * Map window coordinates to object coordinates.
1779 * <p>
1780 * Traditional <code>gluUnProject4</code> implementation.
1781 * </p>
1782 *
1783 * @param winx
1784 * @param winy
1785 * @param winz
1786 * @param clipw
1787 * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
1788 * @param viewport Rect4i viewport vector
1789 * @param near
1790 * @param far
1791 * @param obj_pos 4 component object coordinate, the result
1792 * @return true if successful, otherwise false (null invert matrix, or becomes infinity due to zero z)
1793 */
1794 static bool mapWinToObj4(const value_type winx, const value_type winy, const value_type winz, const value_type clipw,
1795 const Matrix4& invPMv,
1796 const Recti& viewport,
1797 const value_type near, const value_type far,
1798 Vec4& objPos) noexcept
1799 {
1800 Vec4 winPos(winx, winy, winz, clipw);
1801
1802 // Map x and y from window coordinates
1803 winPos.add(-viewport.x(), -viewport.y(), -near, zero).mul(one/viewport.width(), one/viewport.height(), one/(far-near), one);
1804
1805 // Map to range -1 to 1
1806 winPos.mul(two, two, two, one).add(-one, -one, -one, zero);
1807
1808 // objPos = Inv(P x Mv) x winPos
1809 invPMv.mulVec4(winPos, objPos);
1810
1811 if ( zero == objPos.w ) {
1812 return false;
1813 }
1814 return true;
1815 }
1816
1817 /**
1818 * Map two window coordinates w/ shared X/Y and distinctive Z
1819 * to a {@link Ray} in object space.
1820 *
1821 * The resulting {@link Ray} maybe used for <i>picking</i>
1822 * using a {@link AABBox#getRayIntersection(vec3f, Ray, value_type, boolean)}
1823 * of a shape also in object space.
1824 *
1825 * Notes for picking <i>winz0</i> and <i>winz1</i>:
1826 * - see jau::math::util::getZBufferEpsilon()
1827 * - see jau::math::util::getZBufferValue()
1828 * - see jau::math::util::getOrthoWinZ()
1829 * @param winx
1830 * @param winy
1831 * @param winz0
1832 * @param winz1
1833 * @param mMv 4x4 modelview matrix
1834 * @param mP 4x4 projection matrix
1835 * @param viewport Rect4i viewport
1836 * @param ray storage for the resulting {@link Ray} in object space
1837 * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
1838 */
1839 static bool mapWinToObjRay(const value_type winx, const value_type winy, const value_type winz0, const value_type winz1,
1840 const Matrix4& mMv, const Matrix4& mP,
1841 const Recti& viewport,
1842 Ray3& ray) noexcept
1843 {
1844 // invPMv = Inv(P x Mv)
1845 Matrix4 invPMv;
1846 invPMv.mul(mP, mMv);
1847 if( !invPMv.invert() ) {
1848 return false;
1849 }
1850 return mapWinToAnyRay(winx, winy, winz0, winz1, invPMv, viewport, ray);
1851 }
1852
1853 /**
1854 * Map two window coordinates w/ shared X/Y and distinctive Z
1855 * to a {@link Ray} in view space.
1856 *
1857 * The resulting {@link Ray} maybe used for <i>picking</i>
1858 * using a {@link AABBox#getRayIntersection(vec3f, Ray, value_type, boolean)}
1859 * of a shape also in view space.
1860 *
1861 * Notes for picking <i>winz0</i> and <i>winz1</i>:
1862 * - see jau::math::util::getZBufferEpsilon()
1863 * - see jau::math::util::getZBufferValue()
1864 * - see jau::math::util::getOrthoWinZ()
1865 * @param winx
1866 * @param winy
1867 * @param winz0
1868 * @param winz1
1869 * @param mMv 4x4 modelview matrix
1870 * @param mP 4x4 projection matrix
1871 * @param viewport Rect4i viewport
1872 * @param ray storage for the resulting {@link Ray} in view space
1873 * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
1874 */
1875 static bool mapWinToViewRay(const value_type winx, const value_type winy, const value_type winz0, const value_type winz1,
1876 const Matrix4& mP,
1877 const Recti& viewport,
1878 Ray3& ray) noexcept
1879 {
1880 // invP = Inv(P)
1881 Matrix4 invP;
1882 if( !invP.invert(mP) ) {
1883 return false;
1884 }
1885 return mapWinToAnyRay(winx, winy, winz0, winz1, invP, viewport, ray);
1886 }
1887
1888 /**
1889 * Map two window coordinates w/ shared X/Y and distinctive Z
1890 * to a {@link Ray} in object, world or view coordinates, depending on `invAny` argument.
1891 *
1892 * The resulting {@link Ray} maybe used for <i>picking</i>
1893 * using a {@link AABBox#getRayIntersection(vec3f, Ray, value_type, boolean)}
1894 * of a shape also in object, world or view space, see `invAny`.
1895 *
1896 * `invAny` maybe set as follows for
1897 * - to object: inverse(P x Mv) = `([projection] x [modelview])'`
1898 * - to world: inverse(P x V) = `([projection] x [view])'`
1899 * - to view: inverse(P) = `[projection]'`
1900 *
1901 * Notes for picking <i>winz0</i> and <i>winz1</i>:
1902 * - see jau::math::util::getZBufferEpsilon()
1903 * - see jau::math::util::getZBufferValue()
1904 * - see jau::math::util::getOrthoWinZ()
1905 * @param winx
1906 * @param winy
1907 * @param winz0
1908 * @param winz1
1909 * @param invAny inverse matrix, either Inv(P x Mv) to object, Inv(P x V) to world or
1910 Inv(P) `[projection]'` to view
1911 * @param viewport Rect4i viewport
1912 * @param ray storage for the resulting {@link Ray} in object space
1913 * @return true if successful, otherwise false (failed invert matrix, or becomes z is infinity)
1914 */
1915 static bool mapWinToAnyRay(const value_type winx, const value_type winy, const value_type winz0, const value_type winz1,
1916 const Matrix4& invAny,
1917 const Recti& viewport,
1918 Ray3& ray) noexcept
1919 {
1920 if( mapWinToAny(winx, winy, winz0, winz1, invAny, viewport, ray.orig, ray.dir) ) {
1921 (ray.dir -= ray.orig).normalize();
1922 return true;
1923 } else {
1924 return false;
1925 }
1926 }
1927
1928 /**
1929 * Returns a formatted string representation of this matrix
1930 * @param rowPrefix prefix for each row
1931 * @param f format string for each value_type element, e.g. "%10.5f"
1932 */
1933 std::string toString(const std::string& rowPrefix, const std::string& f) const noexcept {
1934 std::string sb;
1935 value_type tmp[16];
1936 get(tmp);
1937 return jau::mat_to_string(sb, rowPrefix, f, tmp, 4, 4, false /* rowMajorOrder */); // creates a copy-out!
1938 }
1939
1940 /**
1941 * Returns a formatted string representation of this matrix
1942 * @param rowPrefix prefix for each row
1943 */
1944 std::string toString(const std::string& rowPrefix) const noexcept { return toString(rowPrefix, "%13.9f"); }
1945
1946 std::string toString() const noexcept { return toString("", "%13.9f"); }
1947};
1948
1949template<typename T,
1950 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
1951constexpr Matrix4<T> operator*(const Matrix4<T>& lhs, const Matrix4<T>& rhs ) noexcept {
1952 Matrix4<T> r(lhs); r.mul(rhs); return r;
1953}
1954
1955template<typename T,
1956 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
1957constexpr Matrix4<T> operator*(const Matrix4<T>& lhs, const T s ) noexcept {
1958 Matrix4<T> r(lhs); r *= s; return r;
1959}
1960
1961template<typename T,
1962 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
1963constexpr Matrix4<T> operator*(const T s, const Matrix4<T>& rhs) noexcept {
1964 Matrix4<T> r(rhs); r *= s; return r;
1965}
1966
1967template<typename T,
1968 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
1969std::ostream& operator<<(std::ostream& out, const Matrix4<T>& v) noexcept {
1970 return out << v.toString();
1971}
1972
1974
1975static_assert(alignof(float) == alignof(Mat4f));
1976static_assert(sizeof(float)*16 == sizeof(Mat4f));
1977
1978/**@}*/
1979
1980} // namespace jau::math
1981
1982#endif // JAU_MATH_MAT4f_HPP_
#define E_FILE_LINE
Horizontal and vertical field of view (FOV) halves, allowing a non-centered projection.
float top
Half vertical FOV from center to top, either in inTangents or radians.
float right
Half horizontal FOV from center to right, either in inTangents or radians.
float left
Half horizontal FOV from center to left, either in inTangents or radians.
FovHVHalves toTangents() const noexcept
Returns this instance in tangent values.
float bottom
Half vertical FOV from center to bottom, either in inTangents or radians.
Basic 4x4 value_type matrix implementation using fields for intensive use-cases (host operations).
Definition mat4f.hpp:101
constexpr Matrix4 & scale(const value_type s) noexcept
Scale this matrix, i.e.
Definition mat4f.hpp:1487
constexpr Matrix4 & setToScale(const value_type x, const value_type y, const value_type z) noexcept
Set this matrix to scale.
Definition mat4f.hpp:955
constexpr bool operator==(const Matrix4 &rhs) const noexcept
Definition mat4f.hpp:206
constexpr value_type get(const jau::nsize_t i) const noexcept
Returns the ith component of the given column-major order matrix, 0 <= i < 16, w/o boundary check.
Definition mat4f.hpp:296
constexpr iterator get(iterator dst) const noexcept
Get this matrix into the given value_type[16] array in column major order w/o boundary check.
Definition mat4f.hpp:389
static bool mapViewToWin(const Vec3 &view, const Matrix4 &mP, const Recti &viewport, Vec3 &winPos) noexcept
Map view coordinates ( Mv x object ) to window coordinates.
Definition mat4f.hpp:1560
constexpr_cxx26 Matrix4 & setToRotationAxis(const value_type ang_rad, value_type x, value_type y, value_type z) noexcept
Set this matrix to rotation from the given axis and angle in radians.
Definition mat4f.hpp:999
value_type * pointer
Definition mat4f.hpp:104
constexpr Matrix4 & translate(const value_type x, const value_type y, const value_type z) noexcept
Translate this matrix, i.e.
Definition mat4f.hpp:1445
constexpr Vec4 getRow(const jau::nsize_t row) const noexcept
Get the named column of the given column-major matrix to v_out w/o boundary check.
Definition mat4f.hpp:361
static constexpr const value_type one
Definition mat4f.hpp:117
std::string toString() const noexcept
Definition mat4f.hpp:1946
constexpr void set(const jau::nsize_t i, const value_type v) noexcept
Sets the ith component of this column-major order matrix with value_type v, 0 <= i < 16 w/o boundary ...
Definition mat4f.hpp:221
constexpr value_type operator[](size_t i) const noexcept
Returns read-only ith component of the given column-major order matrix, 0 <= i < 16 w/o boundary chec...
Definition mat4f.hpp:290
constexpr_cxx26 Matrix4 & setToRotationAxis(const value_type ang_rad, const Vec3 &axis) noexcept
Set this matrix to rotation from the given axis and angle in radians.
Definition mat4f.hpp:1050
bool invert() noexcept
Invert this matrix.
Definition mat4f.hpp:511
static bool mapWinToViewRay(const value_type winx, const value_type winy, const value_type winz0, const value_type winz1, const Matrix4 &mP, const Recti &viewport, Ray3 &ray) noexcept
Map two window coordinates w/ shared X/Y and distinctive Z to a Ray in view space.
Definition mat4f.hpp:1875
Matrix4 & setToPerspective(const FovHVHalves &fovhv, const value_type zNear, const value_type zFar)
Set this matrix to perspective frustum projection.
Definition mat4f.hpp:1294
Value_type value_type
Definition mat4f.hpp:103
constexpr Vec3 & getColumn(const jau::nsize_t column, Vec3 &v_out) const noexcept
Get the named column of the given column-major matrix to v_out w/o boundary check.
Definition mat4f.hpp:337
constexpr Vec3 & mulVec3(const Vec3 &v_in, Vec3 &v_out) const noexcept
Affine 3f-vector transformation by 4x4 matrix.
Definition mat4f.hpp:851
constexpr const_iterator cbegin() const noexcept
Definition mat4f.hpp:302
constexpr reference operator[](size_t i) noexcept
Returns writable reference to the ith component of this column-major order matrix,...
Definition mat4f.hpp:215
Matrix4 & transpose() noexcept
Transpose this matrix.
Definition mat4f.hpp:445
static bool mapWinToAny(const value_type winx, const value_type winy, const value_type winz1, const value_type winz2, const Matrix4 &invAny, const Recti &viewport, Vec3 &objPos1, Vec3 &objPos2) noexcept
Map two window coordinates to two to object, world or view coordinates, depending on invAny argument.
Definition mat4f.hpp:1706
static bool mapWinToView(const value_type winx, const value_type winy, const value_type winz, const Matrix4 &mP, const Recti &viewport, Vec3 &viewPos) noexcept
Map window coordinates to view coordinates.
Definition mat4f.hpp:1628
constexpr Matrix4 & scale(const Vec3 &sxyz) noexcept
Scale this matrix, i.e.
Definition mat4f.hpp:1477
constexpr Vec4 & mulVec4(const Vec4 &v_in, Vec4 &v_out) const noexcept
Definition mat4f.hpp:803
constexpr Vec4 getColumn(const jau::nsize_t column) const noexcept
Get the named column of the given column-major matrix to v_out w/o boundary check.
Definition mat4f.hpp:323
value_type determinant() const noexcept
Returns the determinant of this matrix.
Definition mat4f.hpp:431
static bool mapWinToObj4(const value_type winx, const value_type winy, const value_type winz, const value_type clipw, const Matrix4 &mMv, const Matrix4 &mP, const Recti &viewport, const value_type near, const value_type far, Vec4 &objPos) noexcept
Map window coordinates to object coordinates.
Definition mat4f.hpp:1761
Quaternion< value_type, std::is_floating_point_v< Value_type > > Quat
Definition mat4f.hpp:114
Matrix4 & rotate(const Quat &quat) noexcept
Rotate this matrix with the given Quaternion, i.e.
constexpr_cxx26 Matrix4 & rotate(const value_type ang_rad, const value_type x, const value_type y, const value_type z) noexcept
Rotate this matrix about give axis and angle in radians, i.e.
Definition mat4f.hpp:1414
Matrix4 & setToPerspective(const value_type fovy_rad, const value_type aspect, const value_type zNear, const value_type zFar)
Set this matrix to perspective frustum projection.
Definition mat4f.hpp:1275
Vector4F< value_type > Vec4
Definition mat4f.hpp:112
constexpr Matrix4 & translate(const Vec3 &t) noexcept
Translate this matrix, i.e.
Definition mat4f.hpp:1455
constexpr bool equals(const Matrix4 &o, const value_type epsilon=std::numeric_limits< value_type >::epsilon()) const noexcept
Definition mat4f.hpp:184
const value_type & const_reference
Definition mat4f.hpp:107
constexpr Matrix4 & scale(const value_type x, const value_type y, const value_type z) noexcept
Definition mat4f.hpp:1467
constexpr Vec3 & mulVec3(Vec3 &v_inout) const noexcept
Affine 3f-vector transformation by 4x4 matrix: v_inout = this * v_inout.
Definition mat4f.hpp:886
constexpr iterator begin() noexcept
Definition mat4f.hpp:227
static bool mapObjToWin(const Vec3 &obj, const Matrix4 &mPMv, const Recti &viewport, Vec3 &winPos) noexcept
Map object coordinates to window coordinates.
Definition mat4f.hpp:1507
std::string toString(const std::string &rowPrefix, const std::string &f) const noexcept
Definition mat4f.hpp:1933
Ray3F< value_type > Ray3
Definition mat4f.hpp:113
static bool mapWinToObj(const value_type winx, const value_type winy, const value_type winz, const Matrix4 &mMv, const Matrix4 &mP, const Recti &viewport, Vec3 &objPos) noexcept
Map window coordinates to object coordinates.
Definition mat4f.hpp:1603
Matrix4 & setToFrustum(const value_type left, const value_type right, const value_type bottom, const value_type top, const value_type zNear, const value_type zFar)
Set this matrix to frustum.
Definition mat4f.hpp:1226
constexpr Vec3 operator*(const Vec3 &rhs) const noexcept
Returns new Vec3, with affine 3f-vector transformation by this 4x4 matrix: this x v_in.
Definition mat4f.hpp:868
constexpr Matrix4 & mul(const Matrix4 &a, const Matrix4 &b) noexcept
Multiply matrix: [this] = [a] x [b].
Definition mat4f.hpp:770
Matrix4 & transpose(const Matrix4 &src) noexcept
Transpose the given src matrix into this matrix.
Definition mat4f.hpp:481
constexpr Vec4 & getColumn(const jau::nsize_t column, Vec4 &v_out) const noexcept
Get the named column of the given column-major matrix to v_out w/o boundary check.
Definition mat4f.hpp:310
static bool mapWinToAny(const value_type winx, const value_type winy, const value_type winz, const Matrix4 &invAny, const Recti &viewport, Vec3 &objPos) noexcept
Definition mat4f.hpp:1660
static bool mapObjToWin(const Vec3 &obj, const Matrix4 &mMv, const Matrix4 &mP, const Recti &viewport, Vec3 &winPos) noexcept
Map object coordinates to window coordinates.
Definition mat4f.hpp:1527
constexpr Vec4 operator*(const Vec4 &rhs) const noexcept
Returns new Vec4, with this x v_in.
Definition mat4f.hpp:817
constexpr Vec4 & getRow(const jau::nsize_t row, Vec4 &v_out) const noexcept
Get the named row of the given column-major matrix to v_out w/ boundary check.
Definition mat4f.hpp:349
constexpr Matrix4 & operator*=(const Matrix4 &rhs) noexcept
Multiply matrix: [this] = [this] x [b].
Definition mat4f.hpp:759
constexpr Matrix4 & loadIdentity() noexcept
Set this matrix to identity.
Definition mat4f.hpp:240
constexpr Matrix4 & operator=(const Matrix4 &o) noexcept
Copy assignment using the the values of the given src matrix.
Definition mat4f.hpp:182
static constexpr const value_type half
Definition mat4f.hpp:119
constexpr bool setToPick(const value_type x, const value_type y, const value_type deltaX, const value_type deltaY, const Recti &viewport) noexcept
Set this matrix to the pick matrix based on given parameters.
Definition mat4f.hpp:1386
static constexpr const value_type inv_deviation
Definition mat4f.hpp:127
static constexpr const value_type zero
Definition mat4f.hpp:116
static bool mapWinToObjRay(const value_type winx, const value_type winy, const value_type winz0, const value_type winz1, const Matrix4 &mMv, const Matrix4 &mP, const Recti &viewport, Ray3 &ray) noexcept
Map two window coordinates w/ shared X/Y and distinctive Z to a Ray in object space.
Definition mat4f.hpp:1839
constexpr Vec4 & mulVec4(Vec4 &v_inout) const noexcept
Definition mat4f.hpp:830
std::string toString(const std::string &rowPrefix) const noexcept
Returns a formatted string representation of this matrix.
Definition mat4f.hpp:1944
static bool mapWorldToWin(const Vec3 &world, const Matrix4 &mV, const Matrix4 &mP, const Recti &viewport, Vec3 &winPos) noexcept
Map world coordinates ( M x object ) to window coordinates.
Definition mat4f.hpp:1544
constexpr Matrix4 & setToOrtho(const value_type left, const value_type right, const value_type bottom, const value_type top, const value_type zNear, const value_type zFar) noexcept
Set this matrix to orthogonal projection.
Definition mat4f.hpp:1178
constexpr_cxx26 Matrix4 & setToRotationEuler(const value_type bankX, const value_type headingY, const value_type attitudeZ) noexcept
Set this matrix to rotation from the given Euler rotation angles in radians.
Definition mat4f.hpp:1077
constexpr std::vector< value_type > & get(std::vector< value_type > &dst, size_t dst_off) const noexcept
Get this matrix into the given FloatBuffer in column major order.
Definition mat4f.hpp:417
static bool mapWinToAnyRay(const value_type winx, const value_type winy, const value_type winz0, const value_type winz1, const Matrix4 &invAny, const Recti &viewport, Ray3 &ray) noexcept
Definition mat4f.hpp:1915
constexpr Matrix4 & setToScale(const Vec3 &s) noexcept
Set this matrix to scale.
Definition mat4f.hpp:979
constexpr Matrix4 & operator*=(const value_type s) noexcept
Multiply matrix with scalar: [this] = [this] x [s].
Definition mat4f.hpp:700
constexpr Matrix4(const_iterator m) noexcept
Creates a new matrix based on given value_type[4*4] column major order.
Definition mat4f.hpp:155
bool invert(const Matrix4 &src) noexcept
Invert the src matrix values into this matrix.
Definition mat4f.hpp:592
constexpr_cxx26 Matrix4 & rotate(const value_type ang_rad, const Vec3 &axis) noexcept
Rotate this matrix about give axis and angle in radians, i.e.
Definition mat4f.hpp:1426
constexpr_cxx26 Matrix4 & setToRotationEuler(const Vec3 &angradXYZ) noexcept
Set this matrix to rotation from the given Euler rotation angles in radians.
Definition mat4f.hpp:1130
constexpr Matrix4 & setToTranslation(const Vec3 &t) noexcept
Set this matrix to translation.
Definition mat4f.hpp:937
constexpr Matrix4() noexcept
Creates a new identity matrix.
Definition mat4f.hpp:144
Vector3F< value_type > Vec3
Definition mat4f.hpp:111
value_type * iterator
Definition mat4f.hpp:108
const value_type * const_iterator
Definition mat4f.hpp:109
constexpr Matrix4 & mul(const Matrix4 &b) noexcept
Multiply matrix: [this] = [this] x [b].
Definition mat4f.hpp:714
constexpr Matrix4 & load(const_iterator src) noexcept
Definition mat4f.hpp:254
static bool mapWinToObj4(const value_type winx, const value_type winy, const value_type winz, const value_type clipw, const Matrix4 &invPMv, const Recti &viewport, const value_type near, const value_type far, Vec4 &objPos) noexcept
Map window coordinates to object coordinates.
Definition mat4f.hpp:1794
value_type & reference
Definition mat4f.hpp:106
constexpr Matrix4(const Matrix4 &o) noexcept
Creates a new matrix copying the values of the given src matrix.
Definition mat4f.hpp:175
constexpr Vec3 & getRow(const jau::nsize_t row, Vec3 &v_out) const noexcept
Get the named row of the given column-major matrix to v_out w/o boundary check.
Definition mat4f.hpp:375
constexpr Matrix4 & load(const Matrix4 &src) noexcept
Load the values of the given matrix src to this matrix w/o boundary check.
Definition mat4f.hpp:279
constexpr Matrix4 & setToTranslation(const value_type x, const value_type y, const value_type z) noexcept
Set this matrix to translation.
Definition mat4f.hpp:913
const value_type * const_pointer
Definition mat4f.hpp:105
static constexpr const value_type two
Definition mat4f.hpp:118
constexpr Matrix4(std::initializer_list< value_type > m) noexcept
Creates a new matrix based on given value_type initializer list in column major order.
Definition mat4f.hpp:166
constexpr Matrix4 & setToLookAt(const Vec3 &eye, const Vec3 &center, const Vec3 &up) noexcept
Set this matrix to the look-at matrix based on given parameters.
Definition mat4f.hpp:1322
Quaternion implementation supporting Gimbal-Lock free rotations.
Simple compound denoting a ray.
Definition vec3f.hpp:472
3D vector using three value_type components.
Definition vec3f.hpp:45
value_type x
Definition vec3f.hpp:69
constexpr Vector3F & normalize() noexcept
Normalize this vector in place.
Definition vec3f.hpp:262
constexpr Vector3F cross(const Vector3F &b) const noexcept
cross product this x b
Definition vec3f.hpp:310
value_type y
Definition vec3f.hpp:70
value_type z
Definition vec3f.hpp:71
4D vector using four value_type components.
Definition vec4f.hpp:45
value_type w
Definition vec4f.hpp:72
constexpr Vec3 & getVec3(Vec3 &out) const noexcept
out = { this.x, this.y, this.z } dropping w, returns out.
Definition vec4f.hpp:122
constexpr Vector4F & mul(const Vector4F &s) noexcept
this = this * {s.x, s.y, s.z}, component wise.
Definition vec4f.hpp:157
constexpr Vector4F & add(const Vector4F &d) noexcept
this = this + {d.x, d.y, d.z, d.w}, component wise.
Definition vec4f.hpp:149
value_type z
Definition vec4f.hpp:71
constexpr Vector4F & scale(const value_type s) noexcept
this = this * s, component wise.
Definition vec4f.hpp:165
Providing frustum planes derived by different inputs (P*MV, ..) used to classify objects.
Definition frustum.hpp:78
#define DBG_PRINT(...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
Definition debug.hpp:52
#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::string & mat_to_string(std::string &sb, const std::string &rowPrefix, const std::string &f, const T a[], const jau::nsize_t rows, const jau::nsize_t columns, const bool rowMajorOrder) noexcept
Appends a matrix of floating points to the given string sb
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition int_types.hpp:55
Matrix4< float > Mat4f
Definition mat4f.hpp:1973
constexpr Vector2F< T > max(const Vector2F< T > &lhs, const Vector2F< T > &rhs) noexcept
Definition vec2f.hpp:398
Quat & getRotation(Quat &res) const noexcept
Returns the rotation [m00 .
RectI< int > Recti
Definition recti.hpp:139
constexpr Matrix4< T > operator*(const Matrix4< T > &lhs, const Matrix4< T > &rhs) noexcept
Definition mat4f.hpp:1951
Matrix4 & setToRotation(const Quat &q)
Set this matrix to rotation using the given Quaternion.
std::ostream & operator<<(std::ostream &out, const Addr48Bit &a)
uint8_t Value_type