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