jaulib v1.3.6
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
pmvmat4f.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2014-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_PMVMAT4f_HPP_
25#define JAU_PMVMAT4f_HPP_
26
27#include <cmath>
28#include <cstdarg>
29#include <cstdint>
30#include <cassert>
31#include <string>
32#include <iostream>
33
34#include <jau/functional.hpp>
35#include <jau/basic_types.hpp>
36#include <jau/math/mat4f.hpp>
41
42namespace jau::math::util {
43
44 /** \addtogroup Math
45 *
46 * @{
47 */
48
49
50/**
51 * PMVMatrix4 implements the basic computer graphics Matrix4 pack using
52 * projection (P), modelview (Mv) and texture (T) Matrix4 operations.
53 *
54 * PMVMatrix4 provides the {@link #getMvi() inverse modelview matrix (Mvi)} and
55 * {@link #getMvit() inverse transposed modelview matrix (Mvit)}.
56 * {@link Frustum} is also provided by {@link #getFrustum()}.
57 *
58 * To keep these derived values synchronized after mutable Mv operations like {@link #rotateMv(Quaternion)}
59 * users have to call {@link #update()} before using Mvi and Mvit.
60 *
61 * All matrices are provided in column-major order,
62 * as specified in the OpenGL fixed function pipeline, i.e. compatibility profile.
63 * See Matrix4.
64 *
65 * PMVMatrix4 can supplement {@link com.jogamp.opengl.GL2ES2 GL2ES2} applications w/ the
66 * lack of the described matrix functionality.
67 *
68 * <a name="storageDetails"><h5>Matrix storage details</h5></a>
69 * The native data layout of the matrices are preserved, linear and can be utilized by `GLUniformData`
70 * directly to be pushed to the GPU eventually via SyncMatrix4 and SyncMatrices4,
71 * both SyncBuffer specializations for Matrix4.
72 *
73 * SyncBuffer's provided `sync_action_t` ensures that derived matrices, e.g. getMvi(), are updated before use.
74 *
75 * SyncBuffer's `sync_action_t` is called by `GLUniformData::getBuffer()`
76 * i.e. before the data is pushed to the GPU.
77 */
78
79template<typename Value_type,
80 std::enable_if_t<std::is_floating_point_v<Value_type>, bool> = true>
82 public:
85 typedef const value_type* const_pointer;
89 typedef const value_type* const_iterator;
90
97
98 private:
99 class PMVSync1 : public SyncMat4 {
100 private:
101 const Mat4& m_mat;
102 sync_action_t m_sync;
103
104 public:
105 PMVSync1(const Mat4& m, sync_action_t s) noexcept
106 : m_mat(m), m_sync( std::move(s) )
107 { }
108
109 PMVSync1(const Mat4& m) noexcept
110 : m_mat(m), m_sync( jau::bind_free(sync_action_fptr(nullptr)) )
111 { }
112
113 sync_action_t& action() noexcept override { return m_sync; }
114 const Mat4& matrix() const noexcept override { return m_mat; }
115 };
116
117 class PMVSyncN : public SyncMats4 {
118 private:
119 const Mat4& m_mat;
120 size_t m_count;
121 sync_action_t m_sync;
122
123 public:
124 PMVSyncN(const Mat4& m, size_t count, sync_action_t s) noexcept
125 : m_mat(m), m_count(count), m_sync( std::move(s) )
126 { }
127 PMVSyncN(const Mat4& m, size_t count) noexcept
128 : m_mat(m), m_count(count), m_sync( jau::bind_free(sync_action_fptr(nullptr)) )
129 { }
130
131 sync_action_t& action() noexcept override { return m_sync; }
132 const Mat4* matrices() const noexcept override { return &m_mat; }
133 size_t matrixCount() const noexcept override { return m_count; }
134 };
135
136 Mat4 matP;
137 Mat4 matMv;
138 Mat4 matMvi;
139 Mat4 matMvit;
140
141 Mat4 matTex;
142
143 MatrixStack<value_type> stackMv, stackP, stackTex;
144
145 uint32_t requestBits; // may contain the requested bits: INVERSE_MODELVIEW | INVERSE_TRANSPOSED_MODELVIEW
146
147 PMVSync1 syncP = PMVSync1(matP);
148 PMVSync1 syncMv = PMVSync1(matMv);
149 PMVSync1 syncTex = PMVSync1(matTex);
150
151 PMVSync1 syncMvi = PMVSync1(matMvi, jau::bind_member(this, &PMVMatrix4::updateImpl0));
152 PMVSync1 syncMvit = PMVSync1(matMvit, jau::bind_member(this, &PMVMatrix4::updateImpl0));
153
154 PMVSyncN syncP_Mv = PMVSyncN(matP, 2);
155 PMVSyncN syncP_Mv_Mvi = PMVSyncN(matP, 3, jau::bind_member(this, &PMVMatrix4::updateImpl0));
156 PMVSyncN syncP_Mv_Mvi_Mvit = PMVSyncN(matP, 4, jau::bind_member(this, &PMVMatrix4::updateImpl0));
157
158 uint32_t modifiedBits = MODIFIED_ALL;
159 uint32_t dirtyBits = 0; // contains the dirty bits, i.e. hinting for update operation
160 Mat4 matPMv;
161 Mat4 matPMvi;
162 bool matPMviOK;
163 geom::Frustum frustum;
164
165 constexpr static uint32_t matToReq(uint32_t req) noexcept {
166 int mask = 0;
167 if( 0 != ( req & ( INVERSE_MODELVIEW | INVERSE_TRANSPOSED_MODELVIEW ) ) ) {
168 mask |= INVERSE_MODELVIEW;
169 }
170 if( 0 != ( req & INVERSE_TRANSPOSED_MODELVIEW ) ) {
172 }
173 return mask;
174 }
175
176 public:
177
178 /** Bit value stating a modified {@link #getP() projection matrix (P)}, since last {@link #update()} call. */
179 constexpr static const uint32_t MODIFIED_PROJECTION = 1 << 0;
180 /** Bit value stating a modified {@link #getMv() modelview matrix (Mv)}, since last {@link #update()} call. */
181 constexpr static const uint32_t MODIFIED_MODELVIEW = 1 << 1;
182 /** Bit value stating a modified {@link #getT() texture matrix (T)}, since last {@link #update()} call. */
183 constexpr static const uint32_t MODIFIED_TEXTURE = 1 << 2;
184 /** Bit value stating all is modified */
186 /** Bit value for {@link #getMvi() inverse modelview matrix (Mvi)}, updated via {@link #update()}. */
187 constexpr static const uint32_t INVERSE_MODELVIEW = 1 << 1;
188 /** Bit value for {@link #getMvit() inverse transposed modelview matrix (Mvit)}, updated via {@link #update()}. */
189 constexpr static const uint32_t INVERSE_TRANSPOSED_MODELVIEW = 1 << 2;
190 /** Bit value for {@link #getFrustum() frustum} and updated by {@link #getFrustum()}. */
191 constexpr static const uint32_t FRUSTUM = 1 << 3;
192 /** Bit value for {@link #getPMv() pre-multiplied P * Mv}, updated by {@link #getPMv()}. */
193 constexpr static const uint32_t PREMUL_PMV = 1 << 4;
194 /** Bit value for {@link #getPMvi() pre-multiplied invert(P * Mv)}, updated by {@link #getPMvi()}. */
195 constexpr static const uint32_t PREMUL_PMVI = 1 << 5;
196 /** Manual bits not covered by {@link #update()} but {@link #getFrustum()}, {@link #FRUSTUM}, {@link #getPMv()}, {@link #PREMUL_PMV}, {@link #getPMvi()}, {@link #PREMUL_PMVI}, etc. */
197 constexpr static const uint32_t MANUAL_BITS = FRUSTUM | PREMUL_PMV | PREMUL_PMVI;
198
199 /**
200 * Creates an instance of PMVMatrix4.
201 *
202 * This constructor only sets up an instance w/o additional derived INVERSE_MODELVIEW or INVERSE_TRANSPOSED_MODELVIEW matrices.
203 *
204 * @see #PMVMatrix4(int)
205 */
206 PMVMatrix4() noexcept
207 : PMVMatrix4(0) { }
208
209 /**
210 * Creates an instance of PMVMatrix4.
211 *
212 * Additional derived matrices can be requested via `derivedMatrices`, i.e.
213 * - INVERSE_MODELVIEW
214 * - INVERSE_TRANSPOSED_MODELVIEW
215 *
216 * Implementation uses native Matrix4 elements using column-order fields.
217 * Derived matrices are updated at retrieval, e.g. getMvi(), or via synchronized access, e.g. getSyncMvi(), to the actual Mat4 instances.
218 *
219 * @param derivedMatrices additional matrices can be requested by passing bits {@link #INVERSE_MODELVIEW} and {@link #INVERSE_TRANSPOSED_MODELVIEW}.
220 * @see #getReqBits()
221 * @see #isReqDirty()
222 * @see #getDirtyBits()
223 * @see #update()
224 */
225 PMVMatrix4(int derivedMatrices) noexcept
226 : requestBits( matToReq(derivedMatrices) )
227 {
228 matPMviOK = false;
229 reset();
230 }
231
232 /**
233 * Issues {@link Mat4#loadIdentity()} on all matrices and resets all internal states.
234 */
235 constexpr void reset() noexcept {
236 matP.loadIdentity();
237 matMv.loadIdentity();
238 matTex.loadIdentity();
239
240 modifiedBits = MODIFIED_ALL;
241 dirtyBits = requestBits | MANUAL_BITS;
242 }
243
244 //
245 // Regular Mat4 access as well as their SyncedBuffer counterpart SyncedMatrix and SyncedMatrices
246 //
247
248 /**
249 * Returns the {@link GLMatrixFunc#GL_TEXTURE_MATRIX texture matrix} (T).
250 * <p>
251 * Consider using {@link #setTextureDirty()} if modifying the returned {@link Mat4}.
252 * </p>
253 * <p>
254 * See <a href="#storageDetails"> matrix storage details</a>.
255 * </p>
256 */
257 constexpr Mat4& getT() noexcept { return matTex; }
258 constexpr const Mat4& getT() const noexcept { return matTex; }
259
260 /**
261 * Returns the {@link SyncMatrix} of {@link GLMatrixFunc#GL_TEXTURE_MATRIX texture matrix} (T).
262 * <p>
263 * See <a href="#storageDetails"> matrix storage details</a>.
264 * </p>
265 */
266 constexpr SyncMat4& getSyncT() noexcept { return syncTex; }
267 constexpr const SyncMats4& getSyncT() const noexcept { return syncTex; }
268
269 /**
270 * Returns the {@link GLMatrixFunc#GL_PROJECTION_MATRIX projection matrix} (P).
271 * <p>
272 * Consider using {@link #setProjectionDirty()} if modifying the returned {@link Mat4}.
273 * </p>
274 * <p>
275 * See <a href="#storageDetails"> matrix storage details</a>.
276 * </p>
277 */
278 constexpr Mat4& getP() noexcept { return matP; }
279 constexpr const Mat4& getP() const noexcept { return matP; }
280
281 /**
282 * Returns the {@link SyncMatrix} of {@link GLMatrixFunc#GL_PROJECTION_MATRIX projection matrix} (P).
283 * <p>
284 * See <a href="#storageDetails"> matrix storage details</a>.
285 * </p>
286 */
287 constexpr SyncMat4& getSyncP() noexcept { return syncP; }
288 constexpr const SyncMats4& getSyncP() const noexcept { return syncP; }
289
290 /**
291 * Returns the {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mv).
292 * <p>
293 * Consider using {@link #setModelviewDirty()} if modifying the returned {@link Mat4}.
294 * </p>
295 * <p>
296 * See <a href="#storageDetails"> matrix storage details</a>.
297 * </p>
298 */
299 constexpr Mat4& getMv() noexcept { return matMv; }
300 constexpr const Mat4& getMv() const noexcept { return matMv; }
301
302 /**
303 * Returns the {@link SyncMatrix} of {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mv).
304 * <p>
305 * See <a href="#storageDetails"> matrix storage details</a>.
306 * </p>
307 */
308 constexpr SyncMat4& getSyncMv() noexcept { return syncMv; }
309 constexpr const SyncMats4& getSyncMv() const noexcept { return syncMv; }
310
311 /**
312 * Returns {@link SyncMatrices4f} of 2 matrices within one FloatBuffer: {@link #getP() P} and {@link #getMv() Mv}.
313 * <p>
314 * See <a href="#storageDetails"> matrix storage details</a>.
315 * </p>
316 */
317 constexpr SyncMats4f& getSyncPMv() noexcept { return syncP_Mv; }
318 constexpr const SyncMats4f& getSyncPMv() const noexcept { return syncP_Mv; }
319
320 /**
321 * Returns the inverse {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvi) if requested.
322 * <p>
323 * See <a href="#storageDetails"> matrix storage details</a>.
324 * </p>
325 * @throws IllegalArgumentException if {@link #INVERSE_MODELVIEW} has not been requested in ctor {@link #PMVMatrix4(int)}.
326 */
328 if( 0 == ( INVERSE_MODELVIEW & requestBits ) ) { // FIXME
329 throw jau::IllegalArgumentError("Not requested in ctor", E_FILE_LINE);
330 }
331 updateImpl(false);
332 return matMvi;
333 }
334
335 /**
336 * Returns the {@link SyncMatrix} of inverse {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvi) if requested.
337 * <p>
338 * See <a href="#storageDetails"> matrix storage details</a>.
339 * </p>
340 * @throws IllegalArgumentException if {@link #INVERSE_MODELVIEW} has not been requested in ctor {@link #PMVMatrix4(int)}.
341 */
343 if( 0 == ( INVERSE_MODELVIEW & requestBits ) ) { // FIXME
344 throw jau::IllegalArgumentError("Not requested in ctor", E_FILE_LINE);
345 }
346 return syncMvi;
347 }
348
349 /**
350 * Returns the inverse transposed {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvit) if requested.
351 * <p>
352 * See <a href="#storageDetails"> matrix storage details</a>.
353 * </p>
354 * @throws IllegalArgumentException if {@link #INVERSE_TRANSPOSED_MODELVIEW} has not been requested in ctor {@link #PMVMatrix4(int)}.
355 */
357 if( 0 == ( INVERSE_TRANSPOSED_MODELVIEW & requestBits ) ) { // FIXME
358 throw jau::IllegalArgumentError("Not requested in ctor", E_FILE_LINE);
359 }
360 updateImpl(false);
361 return matMvit;
362 }
363
364 /**
365 * Returns the {@link SyncMatrix} of inverse transposed {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvit) if requested.
366 * <p>
367 * See <a href="#storageDetails"> matrix storage details</a>.
368 * </p>
369 * @throws IllegalArgumentException if {@link #INVERSE_TRANSPOSED_MODELVIEW} has not been requested in ctor {@link #PMVMatrix4(int)}.
370 */
372 if( 0 == ( INVERSE_TRANSPOSED_MODELVIEW & requestBits ) ) { // FIXME
373 throw jau::IllegalArgumentError("Not requested in ctor", E_FILE_LINE);
374 }
375 return syncMvit;
376 }
377
378 /**
379 * Returns {@link SyncMatrices4f} of 3 matrices within one FloatBuffer: {@link #getP() P}, {@link #getMv() Mv} and {@link #getMvi() Mvi} if requested.
380 * <p>
381 * See <a href="#storageDetails"> matrix storage details</a>.
382 * </p>
383 * @throws IllegalArgumentException if {@link #INVERSE_MODELVIEW} has not been requested in ctor {@link #PMVMatrix4(int)}.
384 */
386 if( 0 == ( INVERSE_MODELVIEW & requestBits ) ) { // FIXME
387 throw jau::IllegalArgumentError("Not requested in ctor", E_FILE_LINE);
388 }
389 return syncP_Mv_Mvi;
390 }
391
392 /**
393 * Returns {@link SyncMatrices4f} of 4 matrices within one FloatBuffer: {@link #getP() P}, {@link #getMv() Mv}, {@link #getMvi() Mvi} and {@link #getMvit() Mvit} if requested.
394 * <p>
395 * See <a href="#storageDetails"> matrix storage details</a>.
396 * </p>
397 * @throws IllegalArgumentException if {@link #INVERSE_TRANSPOSED_MODELVIEW} has not been requested in ctor {@link #PMVMatrix4(int)}.
398 */
400 if( 0 == ( INVERSE_TRANSPOSED_MODELVIEW & requestBits ) ) { // FIXME
401 throw jau::IllegalArgumentError("Not requested in ctor", E_FILE_LINE);
402 }
403 return syncP_Mv_Mvi_Mvit;
404 }
405
406 //
407 // Basic Mat4, Vec3 and Vec4 operations similar to GLMatrixFunc
408 //
409
410 /**
411 * Returns multiplication result of {@link #getP() P} and {@link #getMv() Mv} matrix, i.e.
412 * <pre>
413 * result = P x Mv
414 * </pre>
415 * @param result 4x4 matrix storage for result
416 * @return given result matrix for chaining
417 */
418 constexpr Mat4& getMulPMv(Mat4& result) noexcept {
419 return result.mul(matP, matMv);
420 }
421
422 /**
423 * Returns multiplication result of {@link #getMv() Mv} and {@link #getP() P} matrix, i.e.
424 * <pre>
425 * result = Mv x P
426 * </pre>
427 * @param result 4x4 matrix storage for result
428 * @return given result matrix for chaining
429 */
430 constexpr Mat4& getMulMvP(Mat4& result) noexcept {
431 return result.mul(matMv, matP);
432 }
433
434 /**
435 * v_out = Mv * v_in
436 * @param v_in input vector, can be v_out for in-place transformation
437 * @param v_out output vector
438 * @returns v_out for chaining
439 */
440 constexpr Vec4& mulWithMv(const Vec4& v_in, Vec4& v_out) noexcept {
441 return matMv.mulVec4(v_in, v_out);
442 }
443
444 /**
445 * v_inout = Mv * v_inout
446 * @param v_inout input and output vector, i.e. in-place transformation
447 * @returns v_inout for chaining
448 */
449 constexpr Vec4& mulWithMv(Vec4& v_inout) noexcept {
450 return matMv.mulVec4(v_inout);
451 }
452
453 /**
454 * v_out = Mv * v_in
455 *
456 * Affine 3f-vector transformation by 4x4 matrix, see {@link Mat4#mulVec3(Vec3, Vec3)}.
457 *
458 * @param v_in input vector, can be v_out for in-place transformation
459 * @param v_out output vector
460 * @returns v_out for chaining
461 */
462 constexpr Vec3& mulWithMv(const Vec3& v_in, Vec3& v_out) noexcept {
463 return matMv.mulVec3(v_in, v_out);
464 }
465
466 //
467 // GLMatrixFunc alike functionality
468 //
469
470 /**
471 * Load the {@link #getMv() modelview matrix} with the provided values.
472 */
473 constexpr PMVMatrix4& loadMv(float values[]) noexcept {
474 matMv.load(values);
476 return *this;
477 }
478 /**
479 * Load the {@link #getMv() modelview matrix} with the values of the given {@link Mat4}.
480 */
481 constexpr PMVMatrix4& loadMv(const Mat4& m) noexcept {
482 matMv.load(m);
484 return *this;
485 }
486 /**
487 * Load the {@link #getMv() modelview matrix} with the values of the given {@link Quaternion}'s rotation Quaternion::toMatrix() representation.
488 */
489 constexpr PMVMatrix4& loadMv(const Quat4f& quat) noexcept {
490 quat.toMatrix(matMv);
492 return *this;
493 }
494
495 /**
496 * Load the {@link #getP() projection matrix} with the provided values.
497 */
498 constexpr PMVMatrix4& loadP(float values[]) noexcept {
499 matP.load(values);
501 return *this;
502 }
503 /**
504 * Load the {@link #getP() projection matrix} with the values of the given {@link Mat4}.
505 */
506 constexpr PMVMatrix4& loadP(const Mat4& m) {
507 matP.load(m);
509 return *this;
510 }
511 /**
512 * Load the {@link #getP() projection matrix} with the values of the given {@link Quaternion}'s rotation Quaternion::toMatrix() representation.
513 */
514 constexpr PMVMatrix4& loadP(const Quat4f& quat) noexcept {
515 quat.toMatrix(matP);
517 return *this;
518 }
519
520 /**
521 * Load the {@link #getT() texture matrix} with the provided values.
522 */
523 constexpr PMVMatrix4& loadT(float values[]) noexcept {
524 matTex.load(values);
526 return *this;
527 }
528 /**
529 * Load the {@link #getT() texture matrix} with the values of the given {@link Mat4}.
530 */
531 constexpr PMVMatrix4& loadT(Mat4& m) noexcept {
532 matTex.load(m);
534 return *this;
535 }
536 /**
537 * Load the {@link #getT() texture matrix} with the values of the given {@link Quaternion}'s rotation Quaternion::toMatrix() representation.
538 */
539 constexpr PMVMatrix4& loadT(const Quat4f& quat) noexcept {
540 quat.toMatrix(matTex);
542 return *this;
543 }
544
545 /**
546 * Load the {@link #getMv() modelview matrix} with the values of the given {@link Mat4}.
547 */
548 constexpr PMVMatrix4& loadMvIdentity() noexcept {
549 matMv.loadIdentity();
551 return *this;
552 }
553
554 /**
555 * Load the {@link #getP() projection matrix} with the values of the given {@link Mat4}.
556 */
557 constexpr PMVMatrix4& loadPIdentity() noexcept {
558 matP.loadIdentity();
560 return *this;
561 }
562
563 /**
564 * Load the {@link #getT() texture matrix} with the values of the given {@link Mat4}.
565 */
566 constexpr PMVMatrix4& loadTIdentity() noexcept {
567 matTex.loadIdentity();
569 return *this;
570 }
571
572 /**
573 * Multiply the {@link #getMv() modelview matrix}: [c] = [c] x [m]
574 * @param m the right hand Mat4
575 * @return *this instance of chaining
576 */
577 constexpr PMVMatrix4& mulMv(const Mat4& m) noexcept {
578 matMv.mul( m );
580 return *this;
581 }
582
583 /**
584 * Multiply the {@link #getP() projection matrix}: [c] = [c] x [m]
585 * @param m the right hand Mat4
586 * @return *this instance of chaining
587 */
588 constexpr PMVMatrix4& mulP(const Mat4& m) noexcept {
589 matP.mul( m );
591 return *this;
592 }
593
594 /**
595 * Multiply the {@link #getT() texture matrix}: [c] = [c] x [m]
596 * @param m the right hand Mat4
597 * @return *this instance of chaining
598 */
599 constexpr PMVMatrix4& mulT(const Mat4& m) noexcept {
600 matTex.mul( m );
602 return *this;
603 }
604
605 /**
606 * Translate the {@link #getMv() modelview matrix}.
607 * @param x
608 * @param y
609 * @param z
610 * @return *this instance of chaining
611 */
612 constexpr PMVMatrix4& translateMv(float x, float y, float z) noexcept {
613 Mat4 mat4Tmp1;
614 return mulMv( mat4Tmp1.setToTranslation(x, y, z) );
615 }
616 /**
617 * Translate the {@link #getMv() modelview matrix}.
618 * @param t translation vec3
619 * @return *this instance of chaining
620 */
621 constexpr PMVMatrix4& translateMv(const Vec3& t) noexcept {
622 Mat4 mat4Tmp1;
623 return mulMv( mat4Tmp1.setToTranslation(t) );
624 }
625
626 /**
627 * Translate the {@link #getP() projection matrix}.
628 * @param x
629 * @param y
630 * @param z
631 * @return *this instance of chaining
632 */
633 constexpr PMVMatrix4& translateP(float x, float y, float z) noexcept {
634 Mat4 mat4Tmp1;
635 return mulP( mat4Tmp1.setToTranslation(x, y, z) );
636 }
637 /**
638 * Translate the {@link #getP() projection matrix}.
639 * @param t translation vec3
640 * @return *this instance of chaining
641 */
642 constexpr PMVMatrix4& translateP(const Vec3& t) noexcept {
643 Mat4 mat4Tmp1;
644 return mulP( mat4Tmp1.setToTranslation(t) );
645 }
646
647 /**
648 * Scale the {@link #getMv() modelview matrix}.
649 * @param x
650 * @param y
651 * @param z
652 * @return *this instance of chaining
653 */
654 constexpr PMVMatrix4& scaleMv(float x, float y, float z) noexcept {
655 Mat4 mat4Tmp1;
656 return mulMv( mat4Tmp1.setToScale(x, y, z) );
657 }
658 /**
659 * Scale the {@link #getMv() modelview matrix}.
660 * @param s scale vec4f
661 * @return *this instance of chaining
662 */
663 constexpr PMVMatrix4& scaleMv(const Vec3& s) noexcept {
664 Mat4 mat4Tmp1;
665 return mulMv( mat4Tmp1.setToScale(s) );
666 }
667
668 /**
669 * Scale the {@link #getP() projection matrix}.
670 * @param x
671 * @param y
672 * @param z
673 * @return *this instance of chaining
674 */
675 constexpr PMVMatrix4& scaleP(float x, float y, float z) noexcept {
676 Mat4 mat4Tmp1;
677 return mulP( mat4Tmp1.setToScale(x, y, z) );
678 }
679 /**
680 * Scale the {@link #getP() projection matrix}.
681 * @param s scale vec4f
682 * @return *this instance of chaining
683 */
684 constexpr PMVMatrix4& scaleP(const Vec3& s) noexcept {
685 Mat4 mat4Tmp1;
686 return mulP( mat4Tmp1.setToScale(s) );
687 }
688
689 /**
690 * Rotate the {@link #getMv() modelview matrix} by the given axis and angle in radians.
691 * <p>
692 * Consider using {@link #rotateMv(Quaternion)}
693 * </p>
694 * @param ang_rad angle in radians
695 * @param axis rotation axis
696 * @return *this instance of chaining
697 * @see #rotateMv(Quaternion)
698 */
699 constexpr_cxx26 PMVMatrix4& rotateMv(const float ang_rad, const float x, const float y, const float z) noexcept {
700 Mat4 mat4Tmp1;
701 return mulMv( mat4Tmp1.setToRotationAxis(ang_rad, x, y, z) );
702 }
703 /**
704 * Rotate the {@link #getMv() modelview matrix} by the given axis and angle in radians.
705 * <p>
706 * Consider using {@link #rotateMv(Quaternion)}
707 * </p>
708 * @param ang_rad angle in radians
709 * @param axis rotation axis
710 * @return *this instance of chaining
711 * @see #rotateMv(Quaternion)
712 */
713 constexpr_cxx26 PMVMatrix4& rotateMv(const float ang_rad, const Vec3& axis) noexcept {
714 Mat4 mat4Tmp1;
715 return mulMv( mat4Tmp1.setToRotationAxis(ang_rad, axis) );
716 }
717 /**
718 * Rotate the {@link #getMv() modelview matrix} with the given {@link Quaternion}'s rotation {@link Mat4#setToRotation(Quaternion) matrix representation}.
719 * @param quat the {@link Quaternion}
720 * @return *this instance of chaining
721 */
722 constexpr PMVMatrix4& rotateMv(const Quat4f& quat) noexcept {
723 Mat4 mat4Tmp1;
724 return mulMv( quat.toMatrix(mat4Tmp1) );
725 }
726
727 /**
728 * Rotate the {@link #getP() projection matrix} by the given axis and angle in radians.
729 * <p>
730 * Consider using {@link #rotateP(Quaternion)}
731 * </p>
732 * @param ang_rad angle in radians
733 * @param axis rotation axis
734 * @return *this instance of chaining
735 * @see #rotateP(Quaternion)
736 */
737 constexpr_cxx26 PMVMatrix4& rotateP(const float ang_rad, const float x, const float y, const float z) noexcept {
738 Mat4 mat4Tmp1;
739 return mulP( mat4Tmp1.setToRotationAxis(ang_rad, x, y, z) );
740 }
741 /**
742 * Rotate the {@link #getP() projection matrix} by the given axis and angle in radians.
743 * <p>
744 * Consider using {@link #rotateP(Quaternion)}
745 * </p>
746 * @param ang_rad angle in radians
747 * @param axis rotation axis
748 * @return *this instance of chaining
749 * @see #rotateP(Quaternion)
750 */
751 constexpr_cxx26 PMVMatrix4& rotateP(const float ang_rad, const Vec3& axis) noexcept {
752 Mat4 mat4Tmp1;
753 return mulP( mat4Tmp1.setToRotationAxis(ang_rad, axis) );
754 }
755 /**
756 * Rotate the {@link #getP() projection matrix} with the given {@link Quaternion}'s rotation {@link Mat4#setToRotation(Quaternion) matrix representation}.
757 * @param quat the {@link Quaternion}
758 * @return *this instance of chaining
759 */
760 constexpr PMVMatrix4& rotateP(const Quat4f& quat) noexcept {
761 Mat4 mat4Tmp1;
762 return mulP( quat.toMatrix(mat4Tmp1) );
763 }
764
765 /** Pop the {@link #getMv() modelview matrix} from its stack. */
767 stackMv.pop(matMv);
769 return *this;
770 }
771 /** Pop the {@link #getP() projection matrix} from its stack. */
773 stackP.pop(matP);
775 return *this;
776 }
777 /** Pop the {@link #getT() texture matrix} from its stack. */
779 stackTex.pop(matTex);
781 return *this;
782 }
783 /** Push the {@link #getMv() modelview matrix} to its stack, while preserving its values. */
785 stackMv.push(matMv);
786 return *this;
787 }
788 /** Push the {@link #getP() projection matrix} to its stack, while preserving its values. */
790 stackP.push(matP);
791 return *this;
792 }
793 /** Push the {@link #getT() texture matrix} to its stack, while preserving its values. */
795 stackTex.push(matTex);
796 return *this;
797 }
798
799 /**
800 * {@link #mulP(Mat4) Multiply} the {@link #getP() projection matrix} with the orthogonal matrix.
801 * @param left
802 * @param right
803 * @param bottom
804 * @param top
805 * @param zNear
806 * @param zFar
807 * @see Mat4#setToOrtho(float, float, float, float, float, float)
808 */
809 constexpr void orthoP(const float left, const float right, const float bottom, const float top, const float zNear, const float zFar) noexcept {
810 Mat4 mat4Tmp1;
811 mulP( mat4Tmp1.setToOrtho(left, right, bottom, top, zNear, zFar) );
812 }
813
814 /**
815 * {@link #mulP(Mat4) Multiply} the {@link #getP() projection matrix} with the frustum matrix.
816 *
817 * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear}
818 * or {@code left == right}, or {@code bottom == top}.
819 * @see Mat4#setToFrustum(float, float, float, float, float, float)
820 */
821 void frustumP(const float left, const float right, const float bottom, const float top, const float zNear, const float zFar) {
822 Mat4 mat4Tmp1;
823 mulP( mat4Tmp1.setToFrustum(left, right, bottom, top, zNear, zFar) );
824 }
825
826 //
827 // Extra functionality
828 //
829
830 /**
831 * {@link #mulP(Mat4) Multiply} the {@link #getP() projection matrix} with the perspective/frustum matrix.
832 *
833 * @param fovy_rad fov angle in radians
834 * @param aspect aspect ratio width / height
835 * @param zNear
836 * @param zFar
837 * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear}
838 * @see Mat4#setToPerspective(float, float, float, float)
839 */
840 PMVMatrix4& perspectiveP(const float fovy_rad, const float aspect, const float zNear, const float zFar) {
841 Mat4 mat4Tmp1;
842 mulP( mat4Tmp1.setToPerspective(fovy_rad, aspect, zNear, zFar) );
843 return *this;
844 }
845
846 /**
847 * {@link #mulP(Mat4) Multiply} the {@link #getP() projection matrix}
848 * with the eye, object and orientation, i.e. {@link Mat4#setToLookAt(Vec3, Vec3, Vec3, Mat4)}.
849 */
850 constexpr PMVMatrix4& lookAtP(const Vec3& eye, const Vec3& center, const Vec3& up) noexcept {
851 Mat4 mat4Tmp2;
852 Mat4 mat4Tmp1;
853 mulP( mat4Tmp1.setToLookAt(eye, center, up, mat4Tmp2) );
854 return *this;
855 }
856
857 /**
858 * Map object coordinates to window coordinates.
859 * <p>
860 * Traditional <code>gluProject</code> implementation.
861 * </p>
862 *
863 * @param objPos 3 component object coordinate
864 * @param viewport Rect4i viewport
865 * @param winPos 3 component window coordinate, the result
866 * @return true if successful, otherwise false (z is 1)
867 */
868 bool mapObjToWin(const Vec3& objPos, const Recti& viewport, Vec3& winPos) noexcept {
869 return Mat4::mapObjToWin(objPos, matMv, matP, viewport, winPos);
870 }
871
872 /**
873 * Map window coordinates to object coordinates.
874 * <p>
875 * Traditional <code>gluUnProject</code> implementation.
876 * </p>
877 *
878 * @param winx
879 * @param winy
880 * @param winz
881 * @param viewport Rect4i viewport
882 * @param objPos 3 component object coordinate, the result
883 * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
884 */
885 bool mapWinToObj(const float winx, const float winy, const float winz,
886 const Recti& viewport, Vec3& objPos) noexcept {
887 if( Mat4::mapWinToObj(winx, winy, winz, getPMvi(), viewport, objPos) ) {
888 return true;
889 } else {
890 return false;
891 }
892 }
893
894 /**
895 * Map window coordinates to object coordinates.
896 * <p>
897 * Traditional <code>gluUnProject4</code> implementation.
898 * </p>
899 *
900 * @param winx
901 * @param winy
902 * @param winz
903 * @param clipw
904 * @param viewport Rect4i viewport
905 * @param near
906 * @param far
907 * @param objPos 4 component object coordinate, the result
908 * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
909 */
910 bool mapWinToObj4(const float winx, const float winy, const float winz, const float clipw,
911 const Recti& viewport, const float near, const float far, Vec4& objPos) noexcept {
912 if( Mat4::mapWinToObj4(winx, winy, winz, clipw, getPMvi(), viewport, near, far, objPos) ) {
913 return true;
914 } else {
915 return false;
916 }
917 }
918
919 /**
920 * Map two window coordinates w/ shared X/Y and distinctive Z
921 * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i>
922 * using a {@link AABBox#getRayIntersection(Vec3, Ray, float, bool) bounding box}.
923 * <p>
924 * Notes for picking <i>winz0</i> and <i>winz1</i>:
925 * <ul>
926 * <li>see {@link FloatUtil#getZBufferEpsilon(int, float, float)}</li>
927 * <li>see {@link FloatUtil#getZBufferValue(int, float, float, float)}</li>
928 * <li>see {@link FloatUtil#getOrthoWinZ(float, float, float)}</li>
929 * </ul>
930 * </p>
931 * @param winx
932 * @param winy
933 * @param winz0
934 * @param winz1
935 * @param viewport
936 * @param ray storage for the resulting {@link Ray}
937 * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
938 */
939 bool mapWinToRay(const float winx, const float winy, const float winz0, const float winz1,
940 const Recti& viewport, Ray3f& ray) noexcept {
941 return Mat4::mapWinToRay(winx, winy, winz0, winz1, getPMvi(), viewport, ray);
942 }
943
944 std::string& toString(std::string& sb, const std::string& f) const noexcept {
945 const bool pmvDirty = 0 != (PREMUL_PMV & dirtyBits);
946 const bool pmvUsed = true; // null != matPMv;
947
948 const bool pmviDirty = 0 != (PREMUL_PMVI & dirtyBits);
949 const bool pmviUsed = true; // null != matPMvi;
950
951 const bool frustumDirty = 0 != (FRUSTUM & dirtyBits);
952 const bool frustumUsed = true; // null != frustum;
953
954 const bool mviDirty = 0 != (INVERSE_MODELVIEW & dirtyBits);
955 const bool mviReq = 0 != (INVERSE_MODELVIEW & requestBits);
956
957 const bool mvitDirty = 0 != (INVERSE_TRANSPOSED_MODELVIEW & dirtyBits);
958 const bool mvitReq = 0 != (INVERSE_TRANSPOSED_MODELVIEW & requestBits);
959
960 const bool modP = 0 != ( MODIFIED_PROJECTION & modifiedBits );
961 const bool modMv = 0 != ( MODIFIED_MODELVIEW & modifiedBits );
962 const bool modT = 0 != ( MODIFIED_TEXTURE & modifiedBits );
963 int count = 3; // P, Mv, T
964
965 sb.append("PMVMatrix4[modified[P ").append(std::to_string(modP)).append(", Mv ").append(std::to_string(modMv)).append(", T ").append(std::to_string(modT));
966 sb.append("], dirty/used[PMv ").append(std::to_string(pmvDirty)).append("/").append(std::to_string(pmvUsed))
967 .append(", Pmvi ").append(std::to_string(pmviDirty)).append("/").append(std::to_string(pmviUsed))
968 .append(", Frustum ").append(std::to_string(frustumDirty)).append("/").append(std::to_string(frustumUsed));
969 sb.append("], dirty/req[Mvi ").append(std::to_string(mviDirty)).append("/").append(std::to_string(mviReq))
970 .append(", Mvit ").append(std::to_string(mvitDirty)).append("/").append(std::to_string(mvitReq)).append("]\n");
971 sb.append(", Projection\n");
972 matP.toString(sb, f);
973 sb.append(", Modelview\n");
974 matMv.toString(sb, f);
975 sb.append(", Texture\n");
976 matTex.toString(sb, f);
977 if( pmvUsed ) {
978 sb.append(", P * Mv\n");
979 matPMv.toString(sb, f);
980 ++count;
981 }
982 if( pmviUsed ) {
983 sb.append(", P * Mv\n");
984 matPMvi.toString(sb, f);
985 ++count;
986 }
987 if( mviReq ) {
988 sb.append(", Inverse Modelview\n");
989 matMvi.toString(sb, f);
990 ++count;
991 }
992 if( mvitReq ) {
993 sb.append(", Inverse Transposed Modelview\n");
994 matMvit.toString(sb, f);
995 ++count;
996 }
997 int tmpCount = 1;
998 if( true ) { // null != mat4Tmp2 ) {
999 ++tmpCount;
1000 }
1001 sb.append(", matrices "+std::to_string(count)+" + "+std::to_string(tmpCount)+" temp = "+std::to_string(count+tmpCount)+"]");
1002 return sb;
1003 }
1004
1005 std::string toString() const noexcept {
1006 std::string sb;
1007 toString(sb, "%13.9f");
1008 return sb;
1009 }
1010
1011 /**
1012 * Returns the modified bits due to mutable operations..
1013 * <p>
1014 * A modified bit is set, if the corresponding matrix had been modified by a mutable operation
1015 * since last {@link #update()} or {@link #getModifiedBits(bool) getModifiedBits(true)} call.
1016 * </p>
1017 * @param clear if true, clears the modified bits, otherwise leaves them untouched.
1018 *
1019 * @see #MODIFIED_PROJECTION
1020 * @see #MODIFIED_MODELVIEW
1021 * @see #MODIFIED_TEXTURE
1022 * @see #getDirtyBits()
1023 * @see #isReqDirty()
1024 */
1025 constexpr uint32_t getModifiedBits(const bool clear) noexcept {
1026 const uint32_t r = modifiedBits;
1027 if(clear) {
1028 modifiedBits = 0;
1029 }
1030 return r;
1031 }
1032
1033 /**
1034 * Returns the dirty bits due to mutable operations,
1035 * i.e.
1036 * - {@link #INVERSE_MODELVIEW} (if requested)
1037 * - {@link #INVERSE_TRANSPOSED_MODELVIEW} (if requested)
1038 * - {@link #FRUSTUM} (always, cleared via {@link #getFrustum()}
1039 * <p>
1040 * A dirty bit is set, if the corresponding matrix had been modified by a mutable operation
1041 * since last {@link #update()} call and requested in the constructor {@link #PMVMatrix4(int)}.
1042 * </p>
1043 * <p>
1044 * {@link #update()} clears the dirty state for the matrices and {@link #getFrustum()} for {@link #FRUSTUM}.
1045 * </p>
1046 *
1047 * @see #isReqDirty()
1048 * @see #INVERSE_MODELVIEW
1049 * @see #INVERSE_TRANSPOSED_MODELVIEW
1050 * @see #FRUSTUM
1051 * @see #PMVMatrix4(int)
1052 * @see #getMvi()
1053 * @see #getMvit()
1054 * @see #getSyncPMvMvi()
1055 * @see #getSyncPMvMviMvit()
1056 * @see #getFrustum()
1057 */
1058 constexpr uint32_t getDirtyBits() noexcept {
1059 return dirtyBits;
1060 }
1061
1062 /**
1063 * Returns true if the one of the {@link #getReqBits() requested bits} are are set dirty due to mutable operations,
1064 * i.e. at least one of
1065 * - {@link #INVERSE_MODELVIEW}
1066 * - {@link #INVERSE_TRANSPOSED_MODELVIEW}
1067 * <p>
1068 * A dirty bit is set, if the corresponding matrix had been modified by a mutable operation
1069 * since last {@link #update()} call and requested in the constructor {@link #PMVMatrix4(int)}.
1070 * </p>
1071 * <p>
1072 * {@link #update()} clears the dirty state for the matrices and {@link #getFrustum()} for {@link #FRUSTUM}.
1073 * </p>
1074 *
1075 * @see #INVERSE_MODELVIEW
1076 * @see #INVERSE_TRANSPOSED_MODELVIEW
1077 * @see #PMVMatrix4(int)
1078 * @see #getMvi()
1079 * @see #getMvit()
1080 * @see #getSyncPMvMvi()
1081 * @see #getSyncPMvMviMvit()
1082 */
1083 constexpr bool isReqDirty() noexcept {
1084 return 0 != ( requestBits & dirtyBits );
1085 }
1086
1087 /**
1088 * Sets the {@link #getMv() Modelview (Mv)} matrix dirty and modified,
1089 * i.e. adds {@link #getReqBits() requested bits} and {@link #MANUAL_BITS} to {@link #getDirtyBits() dirty bits}.
1090 * @see #isReqDirty()
1091 */
1092 constexpr void setModelviewDirty() noexcept {
1093 dirtyBits |= requestBits | MANUAL_BITS ;
1094 modifiedBits |= MODIFIED_MODELVIEW;
1095 }
1096
1097 /**
1098 * Sets the {@link #getP() Projection (P)} matrix dirty and modified,
1099 * i.e. adds {@link #MANUAL_BITS} to {@link #getDirtyBits() dirty bits}.
1100 */
1101 constexpr void setProjectionDirty() noexcept {
1102 dirtyBits |= MANUAL_BITS ;
1103 modifiedBits |= MODIFIED_PROJECTION;
1104 }
1105
1106 /**
1107 * Sets the {@link #getT() Texture (T)} matrix modified.
1108 */
1109 constexpr void setTextureDirty() noexcept {
1110 modifiedBits |= MODIFIED_TEXTURE;
1111 }
1112
1113 /**
1114 * Returns the request bit mask, which uses bit values equal to the dirty mask
1115 * and may contain
1116 * - {@link #INVERSE_MODELVIEW}
1117 * - {@link #INVERSE_TRANSPOSED_MODELVIEW}
1118 * <p>
1119 * The request bit mask is set by in the constructor {@link #PMVMatrix4(int)}.
1120 * </p>
1121 *
1122 * @see #INVERSE_MODELVIEW
1123 * @see #INVERSE_TRANSPOSED_MODELVIEW
1124 * @see #PMVMatrix4(int)
1125 * @see #getMvi()
1126 * @see #getMvit()
1127 * @see #getSyncPMvMvi()
1128 * @see #getSyncPMvMviMvit()
1129 * @see #getFrustum()
1130 */
1131 constexpr uint32_t getReqBits() noexcept {
1132 return requestBits;
1133 }
1134
1135 /**
1136 * Returns the pre-multiplied projection x modelview, P x Mv.
1137 * <p>
1138 * This {@link Mat4} instance should be re-fetched via this method and not locally stored
1139 * to have it updated from a potential modification of underlying projection and/or modelview matrix.
1140 * {@link #update()} has no effect on this {@link Mat4}.
1141 * </p>
1142 * <p>
1143 * This pre-multipled P x Mv is considered dirty, if its corresponding
1144 * {@link #getP() P matrix} or {@link #getMv() Mv matrix} has been modified since its last update.
1145 * </p>
1146 * @see #update()
1147 */
1148 constexpr Mat4& getPMv() noexcept {
1149 if( 0 != ( dirtyBits & PREMUL_PMV ) ) {
1150 matPMv.mul(matP, matMv);
1151 dirtyBits &= ~PREMUL_PMV;
1152 }
1153 return matPMv;
1154 }
1155
1156 /**
1157 * Returns the pre-multiplied inverse projection x modelview,
1158 * if {@link Mat4#invert(Mat4)} succeeded, otherwise `null`.
1159 * <p>
1160 * This {@link Mat4} instance should be re-fetched via this method and not locally stored
1161 * to have it updated from a potential modification of underlying projection and/or modelview matrix.
1162 * {@link #update()} has no effect on this {@link Mat4}.
1163 * </p>
1164 * <p>
1165 * This pre-multipled invert(P x Mv) is considered dirty, if its corresponding
1166 * {@link #getP() P matrix} or {@link #getMv() Mv matrix} has been modified since its last update.
1167 * </p>
1168 * @see #update()
1169 */
1170 constexpr Mat4& getPMvi() noexcept {
1171 if( 0 != ( dirtyBits & PREMUL_PMVI ) ) {
1172 Mat4& mPMv = getPMv();
1173 matPMviOK = matPMvi.invert(mPMv);
1174 dirtyBits &= ~PREMUL_PMVI;
1175 }
1176 return matPMvi; // matPMviOK ? matPMvi : null; // FIXME
1177 }
1178
1179 /**
1180 * Returns the frustum, derived from projection x modelview.
1181 * <p>
1182 * This {@link Frustum} instance should be re-fetched via this method and not locally stored
1183 * to have it updated from a potential modification of underlying projection and/or modelview matrix.
1184 * {@link #update()} has no effect on this {@link Frustum}.
1185 * </p>
1186 * <p>
1187 * The {@link Frustum} is considered dirty, if its corresponding
1188 * {@link #getP() P matrix} or {@link #getMv() Mv matrix} has been modified since its last update.
1189 * </p>
1190 * @see #update()
1191 */
1193 if( 0 != ( dirtyBits & FRUSTUM ) ) {
1194 frustum.setFromMat(getPMv());
1195 dirtyBits &= ~FRUSTUM;
1196 }
1197 return frustum;
1198 }
1199
1200 /**
1201 * Update the derived {@link #getMvi() inverse modelview (Mvi)},
1202 * {@link #getMvit() inverse transposed modelview (Mvit)} matrices
1203 * <b>if</b> they {@link #isReqDirty() are dirty} <b>and</b>
1204 * requested via the constructor {@link #PMVMatrix4(int)}.<br/>
1205 * Hence updates the following dirty bits.
1206 * - {@link #INVERSE_MODELVIEW}
1207 * - {@link #INVERSE_TRANSPOSED_MODELVIEW}
1208 * <p>
1209 * The {@link Frustum} is updated only via {@link #getFrustum()} separately.
1210 * </p>
1211 * <p>
1212 * The Mvi and Mvit matrices are considered dirty, if their corresponding
1213 * {@link #getMv() Mv matrix} has been modified since their last update.
1214 * </p>
1215 * <p>
1216 * Method is automatically called by {@link SyncMat4} and {@link SyncMatrices4f}
1217 * instances {@link SyncAction} as retrieved by e.g. {@link #getSyncMvit()}.
1218 * This ensures an automatic update cycle if used with {@link com.jogamp.opengl.GLUniformData}.
1219 * </p>
1220 * <p>
1221 * Method may be called manually in case mutable operations has been called
1222 * and caller operates on already fetched references, i.e. not calling
1223 * {@link #getMvi()}, {@link #getMvit()} anymore.
1224 * </p>
1225 * <p>
1226 * Method clears the modified bits like {@link #getModifiedBits(bool) getModifiedBits(true)},
1227 * which are set by any mutable operation. The modified bits have no impact
1228 * on this method, but the return value.
1229 * </p>
1230 *
1231 * @return true if any matrix has been modified since last update call or
1232 * if the derived matrices Mvi and Mvit were updated, otherwise false.
1233 * In other words, method returns true if any matrix used by the caller must be updated,
1234 * e.g. uniforms in a shader program.
1235 *
1236 * @see #getModifiedBits(bool)
1237 * @see #isReqDirty()
1238 * @see #INVERSE_MODELVIEW
1239 * @see #INVERSE_TRANSPOSED_MODELVIEW
1240 * @see #PMVMatrix4(int)
1241 * @see #getMvi()
1242 * @see #getMvit()
1243 * @see #getSyncPMvMvi()
1244 * @see #getSyncPMvMviMvit()
1245 */
1246 bool update() {
1247 return updateImpl(true);
1248 }
1249
1250 //
1251 // private
1252 //
1253
1254 private:
1255 void updateImpl0() { updateImpl(false); }
1256 bool updateImpl(bool clearModBits) {
1257 bool mod = 0 != modifiedBits;
1258 if( clearModBits ) {
1259 modifiedBits = 0;
1260 }
1261 if( 0 != ( requestBits & ( ( dirtyBits & ( INVERSE_MODELVIEW | INVERSE_TRANSPOSED_MODELVIEW ) ) ) ) ) { // only if dirt requested & dirty
1262 if( !matMvi.invert(matMv) ) {
1263 throw jau::math::MathDomainError("Invalid source Mv matrix, can't compute inverse", E_FILE_LINE);
1264 }
1265 dirtyBits &= ~INVERSE_MODELVIEW;
1266 mod = true;
1267 }
1268 if( 0 != ( requestBits & ( dirtyBits & INVERSE_TRANSPOSED_MODELVIEW ) ) ) { // only if requested & dirty
1269 matMvit.transpose(matMvi);
1270 dirtyBits &= ~INVERSE_TRANSPOSED_MODELVIEW;
1271 mod = true;
1272 }
1273 return mod;
1274 }
1275};
1276
1277template<typename Value_type,
1278 std::enable_if_t<std::is_floating_point_v<Value_type>, bool> = true>
1279inline std::ostream& operator<<(std::ostream& out, const PMVMatrix4<Value_type>& v) noexcept {
1280 return out << v.toString();
1281}
1282
1284
1285 /**@}*/
1286
1287 } // namespace jau::math::util
1288
1289 #endif // JAU_PMVMAT4f_HPP_
#define E_FILE_LINE
math_error_t::invalid
Basic 4x4 value_type matrix implementation using fields for intensive use-cases (host operations).
Definition mat4f.hpp:113
constexpr Matrix4 & setToScale(const value_type x, const value_type y, const value_type z) noexcept
Set this matrix to scale.
Definition mat4f.hpp:962
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:1006
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, Matrix4 &mat4Tmp) noexcept
Map window coordinates to object coordinates.
Definition mat4f.hpp:1693
static bool mapWinToRay(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, Matrix4 &mat4Tmp1) noexcept
Definition mat4f.hpp:1786
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:1255
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:1206
static bool mapObjToWin(const Vec3 &obj, const Matrix4 &mMv, const Matrix4 &mP, const Recti &viewport, Vec3 &winPos) noexcept
Definition mat4f.hpp:1472
constexpr Matrix4 & setToLookAt(const Vec3 &eye, const Vec3 &center, const Vec3 &up, Matrix4 &tmp) noexcept
Set this matrix to the look-at matrix based on given parameters.
Definition mat4f.hpp:1303
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:1158
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, Matrix4 &mat4Tmp) noexcept
Map window coordinates to object coordinates.
Definition mat4f.hpp:1551
constexpr Matrix4 & setToTranslation(const value_type x, const value_type y, const value_type z) noexcept
Set this matrix to translation.
Definition mat4f.hpp:920
Simple compound denoting a ray.
Definition vec3f.hpp:440
3D vector using three value_type components.
Definition vec3f.hpp:57
4D vector using four value_type components.
Definition vec4f.hpp:57
Providing frustum planes derived by different inputs (P*MV, ..) used to classify objects.
Definition frustum.hpp:91
PMVMatrix4 implements the basic computer graphics Matrix4 pack using projection (P),...
Definition pmvmat4f.hpp:81
constexpr PMVMatrix4 & loadPIdentity() noexcept
Load the projection matrix with the values of the given Mat4.
Definition pmvmat4f.hpp:557
bool mapWinToObj(const float winx, const float winy, const float winz, const Recti &viewport, Vec3 &objPos) noexcept
Map window coordinates to object coordinates.
Definition pmvmat4f.hpp:885
constexpr PMVMatrix4 & loadMvIdentity() noexcept
Load the modelview matrix with the values of the given Mat4.
Definition pmvmat4f.hpp:548
constexpr void orthoP(const float left, const float right, const float bottom, const float top, const float zNear, const float zFar) noexcept
Multiply the projection matrix with the orthogonal matrix.
Definition pmvmat4f.hpp:809
std::string toString() const noexcept
constexpr SyncMat4 & getSyncT() noexcept
Returns the SyncMatrix of texture matrix (T).
Definition pmvmat4f.hpp:266
constexpr PMVMatrix4 & mulT(const Mat4 &m) noexcept
Multiply the texture matrix: [c] = [c] x [m].
Definition pmvmat4f.hpp:599
jau::math::geom::Frustum getFrustum() noexcept
Returns the frustum, derived from projection x modelview.
static constexpr const uint32_t INVERSE_TRANSPOSED_MODELVIEW
Bit value for inverse transposed modelview matrix (Mvit), updated via update().
Definition pmvmat4f.hpp:189
const value_type * const_pointer
Definition pmvmat4f.hpp:85
constexpr PMVMatrix4 & translateP(float x, float y, float z) noexcept
Translate the projection matrix.
Definition pmvmat4f.hpp:633
constexpr bool isReqDirty() noexcept
Returns true if the one of the requested bits are are set dirty due to mutable operations,...
constexpr Mat4 & getPMv() noexcept
Returns the pre-multiplied projection x modelview, P x Mv.
constexpr PMVMatrix4 & mulP(const Mat4 &m) noexcept
Multiply the projection matrix: [c] = [c] x [m].
Definition pmvmat4f.hpp:588
SyncMats4f & getSyncPMvMviMvit()
Returns SyncMatrices4f of 4 matrices within one FloatBuffer: P, Mv, Mvi and Mvit if requested.
Definition pmvmat4f.hpp:399
PMVMatrix4(int derivedMatrices) noexcept
Creates an instance of PMVMatrix4.
Definition pmvmat4f.hpp:225
constexpr const SyncMats4f & getSyncPMv() const noexcept
Definition pmvmat4f.hpp:318
constexpr PMVMatrix4 & loadMv(float values[]) noexcept
Load the modelview matrix with the provided values.
Definition pmvmat4f.hpp:473
bool update()
Update the derived inverse modelview (Mvi), inverse transposed modelview (Mvit) matrices if they are ...
constexpr PMVMatrix4 & loadP(const Quat4f &quat) noexcept
Load the projection matrix with the values of the given Quaternion's rotation Quaternion::toMatrix() ...
Definition pmvmat4f.hpp:514
const value_type & const_reference
Definition pmvmat4f.hpp:87
constexpr PMVMatrix4 & scaleP(const Vec3 &s) noexcept
Scale the projection matrix.
Definition pmvmat4f.hpp:684
constexpr_cxx20 PMVMatrix4 & popT() noexcept
Pop the texture matrix from its stack.
Definition pmvmat4f.hpp:778
constexpr const SyncMats4 & getSyncP() const noexcept
Definition pmvmat4f.hpp:288
SyncMats4f & getSyncPMvMvi()
Returns SyncMatrices4f of 3 matrices within one FloatBuffer: P, Mv and Mvi if requested.
Definition pmvmat4f.hpp:385
constexpr Mat4 & getP() noexcept
Returns the projection matrix (P).
Definition pmvmat4f.hpp:278
static constexpr const uint32_t INVERSE_MODELVIEW
Bit value for inverse modelview matrix (Mvi), updated via update().
Definition pmvmat4f.hpp:187
constexpr SyncMats4f & getSyncPMv() noexcept
Returns SyncMatrices4f of 2 matrices within one FloatBuffer: P and Mv.
Definition pmvmat4f.hpp:317
constexpr Mat4 & getMv() noexcept
Returns the modelview matrix (Mv).
Definition pmvmat4f.hpp:299
Mat4 & getMvit()
Returns the inverse transposed modelview matrix (Mvit) if requested.
Definition pmvmat4f.hpp:356
constexpr PMVMatrix4 & scaleMv(const Vec3 &s) noexcept
Scale the modelview matrix.
Definition pmvmat4f.hpp:663
constexpr_cxx26 PMVMatrix4 & rotateP(const float ang_rad, const Vec3 &axis) noexcept
Rotate the projection matrix by the given axis and angle in radians.
Definition pmvmat4f.hpp:751
constexpr Vec3 & mulWithMv(const Vec3 &v_in, Vec3 &v_out) noexcept
v_out = Mv * v_in
Definition pmvmat4f.hpp:462
constexpr const SyncMats4 & getSyncT() const noexcept
Definition pmvmat4f.hpp:267
constexpr const SyncMats4 & getSyncMv() const noexcept
Definition pmvmat4f.hpp:309
constexpr uint32_t getDirtyBits() noexcept
Returns the dirty bits due to mutable operations, i.e.
constexpr Mat4 & getPMvi() noexcept
Returns the pre-multiplied inverse projection x modelview, if Mat4#invert(Mat4) succeeded,...
constexpr PMVMatrix4 & loadT(float values[]) noexcept
Load the texture matrix with the provided values.
Definition pmvmat4f.hpp:523
Vector4F< value_type, std::is_floating_point_v< Value_type > > Vec4
Definition pmvmat4f.hpp:92
Matrix4< value_type, std::is_floating_point_v< Value_type > > Mat4
Definition pmvmat4f.hpp:94
constexpr uint32_t getModifiedBits(const bool clear) noexcept
Returns the modified bits due to mutable operations.
static constexpr const uint32_t FRUSTUM
Definition pmvmat4f.hpp:191
std::string & toString(std::string &sb, const std::string &f) const noexcept
Definition pmvmat4f.hpp:944
constexpr_cxx26 PMVMatrix4 & rotateMv(const float ang_rad, const float x, const float y, const float z) noexcept
Rotate the modelview matrix by the given axis and angle in radians.
Definition pmvmat4f.hpp:699
SyncMatrix4< value_type, std::is_floating_point_v< Value_type > > SyncMat4
Definition pmvmat4f.hpp:95
constexpr PMVMatrix4 & mulMv(const Mat4 &m) noexcept
Multiply the modelview matrix: [c] = [c] x [m].
Definition pmvmat4f.hpp:577
constexpr PMVMatrix4 & loadMv(const Quat4f &quat) noexcept
Load the modelview matrix with the values of the given Quaternion's rotation Quaternion::toMatrix() r...
Definition pmvmat4f.hpp:489
constexpr_cxx20 PMVMatrix4 & popMv() noexcept
Pop the modelview matrix from its stack.
Definition pmvmat4f.hpp:766
constexpr_cxx20 PMVMatrix4 & pushP() noexcept
Push the projection matrix to its stack, while preserving its values.
Definition pmvmat4f.hpp:789
constexpr PMVMatrix4 & loadTIdentity() noexcept
Load the texture matrix with the values of the given Mat4.
Definition pmvmat4f.hpp:566
constexpr SyncMat4 & getSyncP() noexcept
Returns the SyncMatrix of projection matrix (P).
Definition pmvmat4f.hpp:287
constexpr PMVMatrix4 & scaleP(float x, float y, float z) noexcept
Scale the projection matrix.
Definition pmvmat4f.hpp:675
Vector3F< value_type, std::is_floating_point_v< Value_type > > Vec3
Definition pmvmat4f.hpp:91
SyncMat4 & getSyncMvi()
Returns the SyncMatrix of inverse modelview matrix (Mvi) if requested.
Definition pmvmat4f.hpp:342
constexpr void setModelviewDirty() noexcept
Sets the Modelview (Mv) matrix dirty and modified, i.e.
constexpr_cxx20 PMVMatrix4 & pushMv() noexcept
Push the modelview matrix to its stack, while preserving its values.
Definition pmvmat4f.hpp:784
constexpr PMVMatrix4 & translateMv(float x, float y, float z) noexcept
Translate the modelview matrix.
Definition pmvmat4f.hpp:612
constexpr_cxx26 PMVMatrix4 & rotateP(const float ang_rad, const float x, const float y, const float z) noexcept
Rotate the projection matrix by the given axis and angle in radians.
Definition pmvmat4f.hpp:737
constexpr const Mat4 & getMv() const noexcept
Definition pmvmat4f.hpp:300
constexpr PMVMatrix4 & lookAtP(const Vec3 &eye, const Vec3 &center, const Vec3 &up) noexcept
Multiply the projection matrix with the eye, object and orientation, i.e.
Definition pmvmat4f.hpp:850
constexpr PMVMatrix4 & loadT(Mat4 &m) noexcept
Load the texture matrix with the values of the given Mat4.
Definition pmvmat4f.hpp:531
PMVMatrix4 & perspectiveP(const float fovy_rad, const float aspect, const float zNear, const float zFar)
Multiply the projection matrix with the perspective/frustum matrix.
Definition pmvmat4f.hpp:840
SyncMatrices4< value_type, std::is_floating_point_v< Value_type > > SyncMats4
Definition pmvmat4f.hpp:96
static constexpr const uint32_t MODIFIED_TEXTURE
Definition pmvmat4f.hpp:183
void frustumP(const float left, const float right, const float bottom, const float top, const float zNear, const float zFar)
Multiply the projection matrix with the frustum matrix.
Definition pmvmat4f.hpp:821
constexpr PMVMatrix4 & translateMv(const Vec3 &t) noexcept
Translate the modelview matrix.
Definition pmvmat4f.hpp:621
constexpr SyncMat4 & getSyncMv() noexcept
Returns the SyncMatrix of modelview matrix (Mv).
Definition pmvmat4f.hpp:308
constexpr const Mat4 & getT() const noexcept
Definition pmvmat4f.hpp:258
static constexpr const uint32_t MANUAL_BITS
Definition pmvmat4f.hpp:197
constexpr void setTextureDirty() noexcept
Sets the Texture (T) matrix modified.
constexpr PMVMatrix4 & rotateP(const Quat4f &quat) noexcept
Rotate the projection matrix with the given Quaternion's rotation matrix representation.
Definition pmvmat4f.hpp:760
constexpr_cxx20 PMVMatrix4 & popP() noexcept
Pop the projection matrix from its stack.
Definition pmvmat4f.hpp:772
constexpr void setProjectionDirty() noexcept
Sets the Projection (P) matrix dirty and modified, i.e.
PMVMatrix4() noexcept
Creates an instance of PMVMatrix4.
Definition pmvmat4f.hpp:206
constexpr PMVMatrix4 & rotateMv(const Quat4f &quat) noexcept
Rotate the modelview matrix with the given Quaternion's rotation matrix representation.
Definition pmvmat4f.hpp:722
static constexpr const uint32_t PREMUL_PMVI
Definition pmvmat4f.hpp:195
constexpr Mat4 & getMulPMv(Mat4 &result) noexcept
Returns multiplication result of P and Mv matrix, i.e.
Definition pmvmat4f.hpp:418
constexpr PMVMatrix4 & translateP(const Vec3 &t) noexcept
Translate the projection matrix.
Definition pmvmat4f.hpp:642
constexpr Mat4 & getT() noexcept
Returns the texture matrix (T).
Definition pmvmat4f.hpp:257
constexpr PMVMatrix4 & scaleMv(float x, float y, float z) noexcept
Scale the modelview matrix.
Definition pmvmat4f.hpp:654
constexpr Vec4 & mulWithMv(const Vec4 &v_in, Vec4 &v_out) noexcept
v_out = Mv * v_in
Definition pmvmat4f.hpp:440
constexpr PMVMatrix4 & loadMv(const Mat4 &m) noexcept
Load the modelview matrix with the values of the given Mat4.
Definition pmvmat4f.hpp:481
const value_type * const_iterator
Definition pmvmat4f.hpp:89
static constexpr const uint32_t PREMUL_PMV
Definition pmvmat4f.hpp:193
constexpr Mat4 & getMulMvP(Mat4 &result) noexcept
Returns multiplication result of Mv and P matrix, i.e.
Definition pmvmat4f.hpp:430
constexpr PMVMatrix4 & loadP(const Mat4 &m)
Load the projection matrix with the values of the given Mat4.
Definition pmvmat4f.hpp:506
bool mapWinToObj4(const float winx, const float winy, const float winz, const float clipw, const Recti &viewport, const float near, const float far, Vec4 &objPos) noexcept
Map window coordinates to object coordinates.
Definition pmvmat4f.hpp:910
static constexpr const uint32_t MODIFIED_PROJECTION
Definition pmvmat4f.hpp:179
static constexpr const uint32_t MODIFIED_MODELVIEW
Definition pmvmat4f.hpp:181
constexpr void reset() noexcept
Issues Mat4#loadIdentity() on all matrices and resets all internal states.
Definition pmvmat4f.hpp:235
constexpr const Mat4 & getP() const noexcept
Definition pmvmat4f.hpp:279
constexpr_cxx20 PMVMatrix4 & pushT() noexcept
Push the texture matrix to its stack, while preserving its values.
Definition pmvmat4f.hpp:794
constexpr PMVMatrix4 & loadP(float values[]) noexcept
Load the projection matrix with the provided values.
Definition pmvmat4f.hpp:498
constexpr Vec4 & mulWithMv(Vec4 &v_inout) noexcept
v_inout = Mv * v_inout
Definition pmvmat4f.hpp:449
SyncMat4 & getSyncMvit()
Returns the SyncMatrix of inverse transposed modelview matrix (Mvit) if requested.
Definition pmvmat4f.hpp:371
constexpr_cxx26 PMVMatrix4 & rotateMv(const float ang_rad, const Vec3 &axis) noexcept
Rotate the modelview matrix by the given axis and angle in radians.
Definition pmvmat4f.hpp:713
Ray3F< value_type, std::is_floating_point_v< Value_type > > Ray3
Definition pmvmat4f.hpp:93
bool mapObjToWin(const Vec3 &objPos, const Recti &viewport, Vec3 &winPos) noexcept
Map object coordinates to window coordinates.
Definition pmvmat4f.hpp:868
Mat4 & getMvi()
Returns the inverse modelview matrix (Mvi) if requested.
Definition pmvmat4f.hpp:327
static constexpr const uint32_t MODIFIED_ALL
Bit value stating all is modified.
Definition pmvmat4f.hpp:185
constexpr PMVMatrix4 & loadT(const Quat4f &quat) noexcept
Load the texture matrix with the values of the given Quaternion's rotation Quaternion::toMatrix() rep...
Definition pmvmat4f.hpp:539
bool mapWinToRay(const float winx, const float winy, const float winz0, const float winz1, const Recti &viewport, Ray3f &ray) noexcept
Map two window coordinates w/ shared X/Y and distinctive Z to a Ray.
Definition pmvmat4f.hpp:939
constexpr uint32_t getReqBits() noexcept
Returns the request bit mask, which uses bit values equal to the dirty mask and may contain.
SyncBuffer interface with multiple underlying Matrix4.
Matrix4< value_type, std::is_floating_point_v< value_type > > Mat4
SyncBuffer interface with a single underlying Matrix4.
#define constexpr_cxx20
constexpr qualifier replacement for C++20 constexpr.
#define constexpr_cxx26
jau::function< R(A...)> bind_member(C1 *base, R(C0::*mfunc)(A...)) noexcept
Bind given class instance and non-void member function to an anonymous function using func_member_tar...
jau::function< R(A...)> bind_free(R(*func)(A...)) noexcept
Bind given non-void free-function to an anonymous function using func::free_target_t.
SyncMatrices4< float > SyncMats4f
Ray3F< float > Ray3f
Definition vec3f.hpp:470
jau::function< void()> sync_action_t
Specific data synchronization action implemented by the data provider to update the buffer with the u...
Quaternion< float > Quat4f
RectI< int > Recti
Definition recti.hpp:151
PMVMatrix4< float > PMVMat4f
void(* sync_action_fptr)()
Plain function pointer type matching sync_action_t.
std::ostream & operator<<(std::ostream &out, const PMVMatrix4< Value_type > &v) noexcept
uint8_t Value_type