summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/jogamp/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java104
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java834
2 files changed, 603 insertions, 335 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java b/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java
index a06d5cefc..67d7d48c1 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java
@@ -1791,18 +1791,19 @@ public class Matrix4f {
* @param winx
* @param winy
* @param winz
- * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv)
+ * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
* @param viewport Rect4i viewport
* @param objPos 3 component object coordinate, the result
- * @param mat4Tmp 16 component matrix for temp storage
- * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
+ * @return true if successful, otherwise false (null invert matrix, or becomes infinity due to zero z)
*/
public static boolean mapWinToObj(final float winx, final float winy, final float winz,
final Matrix4f invPMv,
final Recti viewport,
- final Vec3f objPos,
- final Matrix4f mat4Tmp)
+ final Vec3f objPos)
{
+ if( null == invPMv ) {
+ return false;
+ }
final Vec4f winPos = new Vec4f(winx, winy, winz, 1f);
// Map x and y from window coordinates
@@ -1833,18 +1834,19 @@ public class Matrix4f {
* @param winy
* @param winz1
* @param winz2
- * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv)
+ * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
* @param viewport Rect4i viewport vector
* @param objPos1 3 component object coordinate, the result
- * @param mat4Tmp 16 component matrix for temp storage
- * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
+ * @return true if successful, otherwise false (null invert matrix, or becomes infinity due to zero z)
*/
public static boolean mapWinToObj(final float winx, final float winy, final float winz1, final float winz2,
final Matrix4f invPMv,
final Recti viewport,
- final Vec3f objPos1, final Vec3f objPos2,
- final Matrix4f mat4Tmp)
+ final Vec3f objPos1, final Vec3f objPos2)
{
+ if( null == invPMv ) {
+ return false;
+ }
final Vec4f winPos = new Vec4f(winx, winy, winz1, 1f);
// Map x and y from window coordinates
@@ -1928,6 +1930,49 @@ public class Matrix4f {
}
/**
+ * Map window coordinates to object coordinates.
+ * <p>
+ * Traditional <code>gluUnProject4</code> implementation.
+ * </p>
+ *
+ * @param winx
+ * @param winy
+ * @param winz
+ * @param clipw
+ * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
+ * @param viewport Rect4i viewport vector
+ * @param near
+ * @param far
+ * @param obj_pos 4 component object coordinate, the result
+ * @return true if successful, otherwise false (null invert matrix, or becomes infinity due to zero z)
+ */
+ public static boolean mapWinToObj4(final float winx, final float winy, final float winz, final float clipw,
+ final Matrix4f invPMv,
+ final Recti viewport,
+ final float near, final float far,
+ final Vec4f objPos)
+ {
+ if( null == invPMv ) {
+ return false;
+ }
+ final Vec4f winPos = new Vec4f(winx, winy, winz, clipw);
+
+ // Map x and y from window coordinates
+ winPos.add(-viewport.x(), -viewport.y(), -near, 0f).scale(1f/viewport.width(), 1f/viewport.height(), 1f/(far-near), 1f);
+
+ // Map to range -1 to 1
+ winPos.scale(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
+
+ // objPos = Inv(P x Mv) * winPos
+ invPMv.mulVec4f(winPos, objPos);
+
+ if ( objPos.w() == 0.0f ) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
* Map two window coordinates w/ shared X/Y and distinctive Z
* to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i>
* using a {@link AABBox#getRayIntersection(Vec3f, Ray, float, boolean)}.
@@ -1952,8 +1997,7 @@ public class Matrix4f {
* @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
*/
public static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1,
- final Matrix4f mMv,
- final Matrix4f mP,
+ final Matrix4f mMv, final Matrix4f mP,
final Recti viewport,
final Ray ray,
final Matrix4f mat4Tmp1, final Matrix4f mat4Tmp2) {
@@ -1963,8 +2007,40 @@ public class Matrix4f {
return false;
}
- if( mapWinToObj(winx, winy, winz0, winz1, invPMv, viewport,
- ray.orig, ray.dir, mat4Tmp2) ) {
+ if( mapWinToObj(winx, winy, winz0, winz1, invPMv, viewport, ray.orig, ray.dir) ) {
+ ray.dir.sub(ray.orig).normalize();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Map two window coordinates w/ shared X/Y and distinctive Z
+ * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i>
+ * using a {@link AABBox#getRayIntersection(Vec3f, Ray, float, boolean)}.
+ * <p>
+ * Notes for picking <i>winz0</i> and <i>winz1</i>:
+ * <ul>
+ * <li>see {@link FloatUtil#getZBufferEpsilon(int, float, float)}</li>
+ * <li>see {@link FloatUtil#getZBufferValue(int, float, float, float)}</li>
+ * <li>see {@link FloatUtil#getOrthoWinZ(float, float, float)}</li>
+ * </ul>
+ * </p>
+ * @param winx
+ * @param winy
+ * @param winz0
+ * @param winz1
+ * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
+ * @param viewport Rect4i viewport
+ * @param ray storage for the resulting {@link Ray}
+ * @return true if successful, otherwise false (null invert matrix, or becomes z is infinity)
+ */
+ public static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1,
+ final Matrix4f invPMv,
+ final Recti viewport,
+ final Ray ray) {
+ if( mapWinToObj(winx, winy, winz0, winz1, invPMv, viewport, ray.orig, ray.dir) ) {
ray.dir.sub(ray.orig).normalize();
return true;
} else {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
index 0cba41f65..c9400889b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
@@ -118,14 +118,18 @@ public final class PMVMatrix implements GLMatrixFunc {
/** Bit value stating all is modified */
public static final int MODIFIED_ALL = MODIFIED_PROJECTION | MODIFIED_MODELVIEW | MODIFIED_TEXTURE ;
- /** Bit value stating a dirty {@link #getMviMat() inverse modelview matrix (Mvi)}. */
- public static final int DIRTY_INVERSE_MODELVIEW = 1 << 0;
- /** Bit value stating a dirty {@link #getMvitMat() inverse transposed modelview matrix (Mvit)}. */
- public static final int DIRTY_INVERSE_TRANSPOSED_MODELVIEW = 1 << 1;
- /** Bit value stating a dirty {@link #getFrustum() frustum}. */
- public static final int DIRTY_FRUSTUM = 1 << 2;
- /** Bit value stating all is dirty */
- public static final int DIRTY_ALL = DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM;
+ /** Bit value for {@link #getMviMat() inverse modelview matrix (Mvi)}, updated via {@link #update()}. */
+ public static final int INVERSE_MODELVIEW = 1 << 1;
+ /** Bit value for {@link #getMvitMat() inverse transposed modelview matrix (Mvit)}, updated via {@link #update()}. */
+ public static final int INVERSE_TRANSPOSED_MODELVIEW = 1 << 2;
+ /** Bit value for {@link #getFrustum() frustum} and updated by {@link #getFrustum()}. */
+ public static final int FRUSTUM = 1 << 3;
+ /** Bit value for {@link #getPMvMat() pre-multiplied P * Mv}, updated by {@link #getPMvMat()}. */
+ public static final int PREMUL_PMV = 1 << 4;
+ /** Bit value for {@link #getPMviMat() pre-multiplied invert(P * Mv)}, updated by {@link #getPMviMat()}. */
+ public static final int PREMUL_PMVI = 1 << 5;
+ /** Manual bits not covered by {@link #update()} but {@link #getFrustum()}, {@link #FRUSTUM}, {@link #getPMvMat()}, {@link #PREMUL_PMV}, {@link #getPMviMat()}, {@link #PREMUL_PMVI}, etc. */
+ public static final int MANUAL_BITS = FRUSTUM | PREMUL_PMV | PREMUL_PMVI;
/**
* @param matrixModeName One of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}
@@ -193,58 +197,131 @@ public final class PMVMatrix implements GLMatrixFunc {
/**
* Creates an instance of PMVMatrix.
* <p>
+ * This constructor only sets up an instance w/o additional {@link #INVERSE_MODELVIEW} or {@link #INVERSE_TRANSPOSED_MODELVIEW}.
+ * </p>
+ * <p>
* Implementation uses non-direct non-NIO Buffers with guaranteed backing array,
- * which allows faster access in Java computation.
+ * which are synchronized to the actual Matrix4f instances.
+ * This allows faster access in Java computation.
* </p>
+ * @see #PMVMatrix(int)
*/
public PMVMatrix() {
- // I Identity
- // T Texture
- // P Projection
- // Mv ModelView
- // Mvi Modelview-Inverse
- // Mvit Modelview-Inverse-Transpose
-
- // actual underlying Matrix4f data
- matP = new Matrix4f();
- matMv = new Matrix4f();
- matMvi = new Matrix4f();
- matMvit = new Matrix4f();
- matTex = new Matrix4f();
-
- // float back buffer for GPU, Matrix4f -> matrixStore via SyncedBuffer
- matrixStore = new float[5*16];
-
- // FloatBuffer for single Matrix4f back-buffer
- matrixP = Buffers.slice2Float(matrixStore, mP_offset, 1*16); // P
- matrixMv = Buffers.slice2Float(matrixStore, mMv_offset, 1*16); // Mv
- matrixMvi = Buffers.slice2Float(matrixStore, mMvi_offset, 1*16); // Mvi
- matrixMvit = Buffers.slice2Float(matrixStore, mMvit_offset, 1*16); // Mvit
- matrixTex = Buffers.slice2Float(matrixStore, mTex_offset, 1*16); // T
-
- // FloatBuffer for aggregated multiple Matrix4f back-buffer
- matrixPMvMvit = Buffers.slice2Float(matrixStore, mP_offset, 4*16); // P + Mv + Mvi + Mvit
- matrixPMvMvi = Buffers.slice2Float(matrixStore, mP_offset, 3*16); // P + Mv + Mvi
- matrixPMv = Buffers.slice2Float(matrixStore, mP_offset, 2*16); // P + Mv
-
- matPSync = new SyncBuffer0(matP, matrixP); // mP_offset
- matMvSync = new SyncBuffer1(matMv, matrixMv, mMv_offset);
- matMviSync = new SyncBuffer1(matMvi, matrixMvi, mMvi_offset);
- matMvitSync = new SyncBuffer1(matMvit, matrixMvit, mMvit_offset);
- matTexSync = new SyncBuffer1(matTex, matrixTex, mTex_offset);
-
- matPMvMvitSync = new SyncBufferN(new Matrix4f[] { matP, matMv, matMvi, matMvit }, matrixPMvMvit, mP_offset);
- matPMvMviSync = new SyncBufferN(new Matrix4f[] { matP, matMv, matMvi }, matrixPMvMvi, mP_offset);
- matPMvSync = new SyncBufferN(new Matrix4f[] { matP, matMv }, matrixPMv, mP_offset);
-
- mat4Tmp1 = new Matrix4f();
- mat4Tmp2 = new Matrix4f();
- vec3Tmp1 = new Vec3f();
- vec4Tmp1 = new Vec4f();
-
- reset();
-
- frustum = null;
+ this(0);
+ }
+
+ /**
+ * Creates an instance of PMVMatrix.
+ * <p>
+ * Additional derived matrices can be requested via `derivedMatrices`, i.e.
+ * - {@link #INVERSE_MODELVIEW}
+ * - {@link #INVERSE_TRANSPOSED_MODELVIEW}
+ * </p>
+ * <p>
+ * Implementation uses non-direct non-NIO Buffers with guaranteed backing array,
+ * which are synchronized to the actual Matrix4f instances.
+ * This allows faster access in Java computation.
+ * </p>
+ * @param derivedMatrices additional matrices can be requested by passing bits {@link #INVERSE_MODELVIEW} and {@link #INVERSE_TRANSPOSED_MODELVIEW}.
+ * @see #getReqBits()
+ * @see #isReqDirty()
+ * @see #getDirtyBits()
+ * @see #update()
+ */
+ public PMVMatrix(final int derivedMatrices) {
+ // I Identity
+ // T Texture
+ // P Projection
+ // Mv ModelView
+ // Mvi Modelview-Inverse
+ // Mvit Modelview-Inverse-Transpose
+ {
+ int mask = 0;
+ if( 0 != ( derivedMatrices & ( INVERSE_MODELVIEW | INVERSE_TRANSPOSED_MODELVIEW ) ) ) {
+ mask |= INVERSE_MODELVIEW;
+ }
+ if( 0 != ( derivedMatrices & INVERSE_TRANSPOSED_MODELVIEW ) ) {
+ mask |= INVERSE_TRANSPOSED_MODELVIEW;
+ }
+ requestBits = mask;
+ }
+
+ // actual underlying Matrix4f count
+ int mcount = 3;
+
+ // actual underlying Matrix4f data
+ matP = new Matrix4f();
+ matMv = new Matrix4f();
+ matTex = new Matrix4f();
+
+ if( 0 != ( requestBits & INVERSE_MODELVIEW ) ) {
+ matMvi = new Matrix4f();
+ mMvi_offset = 2*16;
+ ++mcount;
+ } else {
+ matMvi = null;
+ mMvi_offset = -1;
+ }
+ if( 0 != ( requestBits & INVERSE_TRANSPOSED_MODELVIEW ) ) {
+ matMvit = new Matrix4f();
+ mMvit_offset = 3*16;
+ ++mcount;
+ } else {
+ matMvit = null;
+ mMvit_offset = -1;
+ }
+ mTex_offset = (mcount-1)*16; // last one
+
+ // float back buffer for GPU, Matrix4f -> matrixStore via SyncedBuffer
+ matrixStore = new float[mcount*16];
+
+ // FloatBuffer for single Matrix4f back-buffer
+ bufP = Buffers.slice2Float(matrixStore, mP_offset, 1*16); // P
+ syncP = new SyncBuffer0(matP, bufP); // mP_offset
+
+ bufMv = Buffers.slice2Float(matrixStore, mMv_offset, 1*16); // Mv
+ syncMv = new SyncBuffer1(matMv, bufMv, mMv_offset);
+
+ bufP_Mv = Buffers.slice2Float(matrixStore, mP_offset, 2*16); // P + Mv
+ syncP_Mv = new SyncBufferN(new Matrix4f[] { matP, matMv }, bufP_Mv, mP_offset);
+
+ bufTex = Buffers.slice2Float(matrixStore, mTex_offset, 1*16); // T
+ syncT = new SyncBuffer1(matTex, bufTex, mTex_offset);
+
+ if( null != matMvi ) {
+ bufMvi = Buffers.slice2Float(matrixStore, mMvi_offset, 1*16); // Mvi
+ bufP_Mv_Mvi = Buffers.slice2Float(matrixStore, mP_offset, 3*16); // P + Mv + Mvi
+ syncMvi = new SyncBuffer1U(matMvi, bufMvi, mMvi_offset);
+ syncP_Mv_Mvi = new SyncBufferNU(new Matrix4f[] { matP, matMv, matMvi }, bufP_Mv_Mvi, mP_offset);
+ } else {
+ bufMvi = null;
+ bufP_Mv_Mvi = null;
+ syncMvi = null;
+ syncP_Mv_Mvi = null;
+ }
+ if( null != matMvit ) {
+ bufMvit = Buffers.slice2Float(matrixStore, mMvit_offset, 1*16); // Mvit
+ bufP_Mv_Mvi_Mvit = Buffers.slice2Float(matrixStore, mP_offset, 4*16); // P + Mv + Mvi + Mvit
+ syncMvit = new SyncBuffer1U(matMvit, bufMvit, mMvit_offset);
+ syncP_Mv_Mvi_Mvit = new SyncBufferNU(new Matrix4f[] { matP, matMv, matMvi, matMvit }, bufP_Mv_Mvi_Mvit, mP_offset);
+ } else {
+ bufMvit = null;
+ bufP_Mv_Mvi_Mvit = null;
+ syncMvit = null;
+ syncP_Mv_Mvi_Mvit = null;
+ }
+
+ mat4Tmp1 = new Matrix4f();
+ vec3Tmp1 = new Vec3f();
+ vec4Tmp1 = new Vec4f();
+
+ mat4Tmp2 = null; // on demand
+ matPMv = null; // on demand
+ matPMvi = null; // on demand
+ matPMviOK = false;
+ frustum = null; // on demand
+
+ reset();
}
/**
@@ -260,8 +337,7 @@ public final class PMVMatrix implements GLMatrixFunc {
matTex.loadIdentity();
modifiedBits = MODIFIED_ALL;
- dirtyBits = DIRTY_ALL;
- requestMask = 0;
+ dirtyBits = requestBits | MANUAL_BITS;
matrixMode = GL_MODELVIEW;
}
@@ -275,40 +351,18 @@ public final class PMVMatrix implements GLMatrixFunc {
//
/**
- * Return the first temporary Matrix4f exposed to be reused for efficiency.
- * <p>
- * Temporary storage is only used by this class within single method calls,
- * hence has no side-effects.
- * </p>
- */
- public final Matrix4f getTmp1Mat() { return mat4Tmp1; }
-
- /**
* Return the second temporary Matrix4f exposed to be reused for efficiency.
* <p>
* Temporary storage is only used by this class within single method calls,
* hence has no side-effects.
* </p>
*/
- public final Matrix4f getTmp2Mat() { return mat4Tmp2; }
-
- /**
- * Return the first temporary Vec3f exposed to be reused for efficiency.
- * <p>
- * Temporary storage is only used by this class within single method calls,
- * hence has no side-effects.
- * </p>
- */
- public final Vec3f getTmp1Vec3f() { return vec3Tmp1; }
-
- /**
- * Return the first temporary Vec4f exposed to be reused for efficiency.
- * <p>
- * Temporary storage is only used by this class within single method calls,
- * hence has no side-effects.
- * </p>
- */
- public final Vec4f getTmp1Vec4f() { return vec4Tmp1; }
+ private final Matrix4f getTmp2Mat() {
+ if( null == mat4Tmp2 ) {
+ mat4Tmp2 = new Matrix4f();
+ }
+ return mat4Tmp2;
+ }
//
// Regular Matrix4f access as well as their SyncedBuffer counterpart SyncedMatrix and SyncedMatrices
@@ -331,7 +385,7 @@ public final class PMVMatrix implements GLMatrixFunc {
* </p>
*/
public final SyncMatrix4f getSyncTMat() {
- return matTexSync;
+ return syncT;
}
/**
@@ -351,7 +405,7 @@ public final class PMVMatrix implements GLMatrixFunc {
* </p>
*/
public final SyncMatrix4f getSyncPMat() {
- return matPSync;
+ return syncP;
}
/**
@@ -371,126 +425,103 @@ public final class PMVMatrix implements GLMatrixFunc {
* </p>
*/
public final SyncMatrix4f getSyncMvMat() {
- return matMvSync;
+ return syncMv;
}
/**
- * Returns the inverse {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvi).
+ * Returns {@link SyncMatrices4f} of 2 matrices within one FloatBuffer: {@link #getPMat() P} and {@link #getMvMat() Mv}.
* <p>
- * Method enables the Mvi matrix update, and performs it's update w/o clearing the modified bits.
+ * See <a href="#storageDetails"> matrix storage details</a>.
* </p>
+ */
+ public final SyncMatrices4f getSyncPMvMat() {
+ return syncP_Mv;
+ }
+
+ /**
+ * Returns the inverse {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvi) if requested.
* <p>
- * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
+ * See <a href="#storageDetails"> matrix storage details</a>.
* </p>
- * @see #update()
- * @see #clearAllUpdateRequests()
+ * @throws IllegalArgumentException if {@link #INVERSE_MODELVIEW} has not been requested in ctor {@link #PMVMatrix(int)}.
*/
public final Matrix4f getMviMat() {
- requestMask |= DIRTY_INVERSE_MODELVIEW ;
+ if( 0 == ( INVERSE_MODELVIEW & requestBits ) ) {
+ throw new IllegalArgumentException("Not requested in ctor");
+ }
updateImpl(false);
return matMvi;
}
/**
- * Returns the {@link SyncMatrix} of inverse {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvi).
+ * Returns the {@link SyncMatrix} of inverse {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvi) if requested.
* <p>
- * Method enables the Mvi matrix update, and performs it's update w/o clearing the modified bits.
- * </p>
- * <p>
- * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
+ * See <a href="#storageDetails"> matrix storage details</a>.
* </p>
- * @see #update()
- * @see #clearAllUpdateRequests()
+ * @throws IllegalArgumentException if {@link #INVERSE_MODELVIEW} has not been requested in ctor {@link #PMVMatrix(int)}.
*/
public final SyncMatrix4f getSyncMviMat() {
- requestMask |= DIRTY_INVERSE_MODELVIEW ;
- updateImpl(false);
- return matMviSync;
+ if( 0 == ( INVERSE_MODELVIEW & requestBits ) ) {
+ throw new IllegalArgumentException("Not requested in ctor");
+ }
+ return syncMvi;
}
/**
- * Returns the inverse transposed {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvit).
- * <p>
- * Method enables the Mvit matrix update, and performs it's update w/o clearing the modified bits.
- * </p>
+ * Returns the inverse transposed {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvit) if requested.
* <p>
- * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
+ * See <a href="#storageDetails"> matrix storage details</a>.
* </p>
- * @see #update()
- * @see #clearAllUpdateRequests()
+ * @throws IllegalArgumentException if {@link #INVERSE_TRANSPOSED_MODELVIEW} has not been requested in ctor {@link #PMVMatrix(int)}.
*/
public final Matrix4f getMvitMat() {
- requestMask |= DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
+ if( 0 == ( INVERSE_TRANSPOSED_MODELVIEW & requestBits ) ) {
+ throw new IllegalArgumentException("Not requested in ctor");
+ }
updateImpl(false);
return matMvit;
}
/**
- * Returns the {@link SyncMatrix} of inverse transposed {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvit).
- * <p>
- * Method enables the Mvit matrix update, and performs it's update w/o clearing the modified bits.
- * </p>
+ * Returns the {@link SyncMatrix} of inverse transposed {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvit) if requested.
* <p>
- * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
+ * See <a href="#storageDetails"> matrix storage details</a>.
* </p>
- * @see #update()
- * @see #clearAllUpdateRequests()
+ * @throws IllegalArgumentException if {@link #INVERSE_TRANSPOSED_MODELVIEW} has not been requested in ctor {@link #PMVMatrix(int)}.
*/
public final SyncMatrix4f getSyncMvitMat() {
- requestMask |= DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
- updateImpl(false);
- return matMvitSync;
+ if( 0 == ( INVERSE_TRANSPOSED_MODELVIEW & requestBits ) ) {
+ throw new IllegalArgumentException("Not requested in ctor");
+ }
+ return syncMvit;
}
/**
- * Returns {@link SyncMatrices4f} of 2 matrices within one FloatBuffer: {@link #getPMat() P} and {@link #getMvMat() Mv}.
+ * Returns {@link SyncMatrices4f} of 3 matrices within one FloatBuffer: {@link #getPMat() P}, {@link #getMvMat() Mv} and {@link #getMviMat() Mvi} if requested.
* <p>
* See <a href="#storageDetails"> matrix storage details</a>.
* </p>
- */
- public final SyncMatrices4f getSyncPMvMat() {
- return matPMvSync;
- }
-
- /**
- * Returns {@link SyncMatrices4f} of 3 matrices within one FloatBuffer: {@link #getPMat() P}, {@link #getMvMat() Mv} and {@link #getMviMat() Mvi}.
- * <p>
- * Method enables the Mvi matrix update, and performs it's update w/o clearing the modified bits.
- * </p>
- * <p>
- * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
- * </p>
- * @see #update()
- * @see #clearAllUpdateRequests()
+ * @throws IllegalArgumentException if {@link #INVERSE_MODELVIEW} has not been requested in ctor {@link #PMVMatrix(int)}.
*/
public final SyncMatrices4f getSyncPMvMviMat() {
- requestMask |= DIRTY_INVERSE_MODELVIEW ;
- updateImpl(false);
- return matPMvMviSync;
+ if( 0 == ( INVERSE_MODELVIEW & requestBits ) ) {
+ throw new IllegalArgumentException("Not requested in ctor");
+ }
+ return syncP_Mv_Mvi;
}
/**
- * Returns {@link SyncMatrices4f} of 4 matrices within one FloatBuffer: {@link #getPMat() P}, {@link #getMvMat() Mv}, {@link #getMviMat() Mvi} and {@link #getMvitMat() Mvit}.
- * <p>
- * Method enables the Mvi and Mvit matrix update, and performs it's update w/o clearing the modified bits.
- * </p>
+ * Returns {@link SyncMatrices4f} of 4 matrices within one FloatBuffer: {@link #getPMat() P}, {@link #getMvMat() Mv}, {@link #getMviMat() Mvi} and {@link #getMvitMat() Mvit} if requested.
* <p>
- * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
+ * See <a href="#storageDetails"> matrix storage details</a>.
* </p>
- * @see #update()
- * @see #clearAllUpdateRequests()
+ * @throws IllegalArgumentException if {@link #INVERSE_TRANSPOSED_MODELVIEW} has not been requested in ctor {@link #PMVMatrix(int)}.
*/
- public final SyncMatrices4f getSyncPMvMvitMat() {
- requestMask |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
- updateImpl(false);
- return matPMvMvitSync;
- }
-
- /** Returns the frustum, derived from projection * modelview */
- public final Frustum getFrustum() {
- requestMask |= DIRTY_FRUSTUM;
- updateImpl(false);
- return frustum;
+ public final SyncMatrices4f getSyncPMvMviMvitMat() {
+ if( 0 == ( INVERSE_TRANSPOSED_MODELVIEW & requestBits ) ) {
+ throw new IllegalArgumentException("Not requested in ctor");
+ }
+ return syncP_Mv_Mvi_Mvit;
}
/**
@@ -678,11 +709,11 @@ public final class PMVMatrix implements GLMatrixFunc {
public final void glLoadMatrixf(final float[] values, final int offset) {
if(matrixMode==GL_MODELVIEW) {
matMv.load(values, offset);
- dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ dirtyBits |= requestBits | MANUAL_BITS ;
modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
matP.load(values, offset);
- dirtyBits |= DIRTY_FRUSTUM ;
+ dirtyBits |= MANUAL_BITS ;
modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
matTex.load(values, offset);
@@ -695,11 +726,11 @@ public final class PMVMatrix implements GLMatrixFunc {
final int spos = m.position();
if(matrixMode==GL_MODELVIEW) {
matMv.load(m);
- dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ dirtyBits |= requestBits | MANUAL_BITS ;
modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
matP.load(m);
- dirtyBits |= DIRTY_FRUSTUM ;
+ dirtyBits |= MANUAL_BITS ;
modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
matTex.load(m);
@@ -717,11 +748,11 @@ public final class PMVMatrix implements GLMatrixFunc {
public final void glLoadMatrixf(final Matrix4f m) {
if(matrixMode==GL_MODELVIEW) {
matMv.load(m);
- dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ dirtyBits |= requestBits | MANUAL_BITS ;
modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
matP.load(m);
- dirtyBits |= DIRTY_FRUSTUM ;
+ dirtyBits |= MANUAL_BITS ;
modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
matTex.load(m);
@@ -738,11 +769,11 @@ public final class PMVMatrix implements GLMatrixFunc {
public final void glLoadMatrix(final Quaternion quat) {
if(matrixMode==GL_MODELVIEW) {
matMv.setToRotation(quat);
- dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ dirtyBits |= requestBits | MANUAL_BITS ;
modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
matP.setToRotation(quat);
- dirtyBits |= DIRTY_FRUSTUM ;
+ dirtyBits |= MANUAL_BITS ;
modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
matTex.setToRotation(quat);
@@ -754,10 +785,15 @@ public final class PMVMatrix implements GLMatrixFunc {
public final void glPopMatrix() {
if(matrixMode==GL_MODELVIEW) {
matMv.pop();
+ dirtyBits |= requestBits | MANUAL_BITS ;
+ modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
matP.pop();
+ dirtyBits |= MANUAL_BITS ;
+ modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
matTex.pop();
+ modifiedBits |= MODIFIED_TEXTURE;
}
}
@@ -776,11 +812,11 @@ public final class PMVMatrix implements GLMatrixFunc {
public final void glLoadIdentity() {
if(matrixMode==GL_MODELVIEW) {
matMv.loadIdentity();
- dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ dirtyBits |= requestBits | MANUAL_BITS ;
modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
matP.loadIdentity();
- dirtyBits |= DIRTY_FRUSTUM ;
+ dirtyBits |= MANUAL_BITS ;
modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
matTex.loadIdentity();
@@ -788,17 +824,16 @@ public final class PMVMatrix implements GLMatrixFunc {
}
}
- @SuppressWarnings("deprecation")
@Override
public final void glMultMatrixf(final FloatBuffer m) {
final int spos = m.position();
if(matrixMode==GL_MODELVIEW) {
matMv.mul( mat4Tmp1.load( m ) );
- dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ dirtyBits |= requestBits | MANUAL_BITS ;
modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
matP.mul( mat4Tmp1.load( m ) );
- dirtyBits |= DIRTY_FRUSTUM ;
+ dirtyBits |= MANUAL_BITS ;
modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
matTex.mul( mat4Tmp1.load( m ) );
@@ -811,11 +846,11 @@ public final class PMVMatrix implements GLMatrixFunc {
public final void glMultMatrixf(final float[] m, final int m_offset) {
if(matrixMode==GL_MODELVIEW) {
matMv.mul( mat4Tmp1.load( m, m_offset ) );
- dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ dirtyBits |= requestBits | MANUAL_BITS ;
modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
matP.mul( mat4Tmp1.load( m, m_offset ) );
- dirtyBits |= DIRTY_FRUSTUM ;
+ dirtyBits |= MANUAL_BITS ;
modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
matTex.mul( mat4Tmp1.load( m, m_offset ) );
@@ -834,11 +869,11 @@ public final class PMVMatrix implements GLMatrixFunc {
public final PMVMatrix glMultMatrixf(final Matrix4f m) {
if(matrixMode==GL_MODELVIEW) {
matMv.mul( m );
- dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+ dirtyBits |= requestBits | MANUAL_BITS ;
modifiedBits |= MODIFIED_MODELVIEW;
} else if(matrixMode==GL_PROJECTION) {
matP.mul( m );
- dirtyBits |= DIRTY_FRUSTUM ;
+ dirtyBits |= MANUAL_BITS ;
modifiedBits |= MODIFIED_PROJECTION;
} else if(matrixMode==GL.GL_TEXTURE) {
matTex.mul( m );
@@ -955,7 +990,7 @@ public final class PMVMatrix implements GLMatrixFunc {
* with the eye, object and orientation.
*/
public final void gluLookAt(final Vec3f eye, final Vec3f center, final Vec3f up) {
- glMultMatrixf( mat4Tmp1.setToLookAt(eye, center, up, mat4Tmp2) );
+ glMultMatrixf( mat4Tmp1.setToLookAt(eye, center, up, getTmp2Mat()) );
}
/**
@@ -988,7 +1023,7 @@ public final class PMVMatrix implements GLMatrixFunc {
*/
public final boolean gluUnProject(final float winx, final float winy, final float winz,
final Recti viewport, final Vec3f objPos) {
- if( Matrix4f.mapWinToObj(winx, winy, winz, matMv, matP, viewport, objPos, mat4Tmp1) ) {
+ if( Matrix4f.mapWinToObj(winx, winy, winz, getPMviMat(), viewport, objPos) ) {
return true;
} else {
return false;
@@ -1015,7 +1050,7 @@ public final class PMVMatrix implements GLMatrixFunc {
final Recti viewport,
final float near, final float far,
final Vec4f objPos) {
- if( Matrix4f.mapWinToObj4(winx, winy, winz, clipw, matMv, matP, viewport, near, far, objPos, mat4Tmp1) ) {
+ if( Matrix4f.mapWinToObj4(winx, winy, winz, clipw, getPMviMat(), viewport, near, far, objPos) ) {
return true;
} else {
return false;
@@ -1023,27 +1058,6 @@ public final class PMVMatrix implements GLMatrixFunc {
}
/**
- * Make given matrix the <i>pick</i> matrix based on given parameters.
- * <p>
- * Traditional <code>gluPickMatrix</code> implementation.
- * </p>
- * <p>
- * See {@link Matrix4f#setToPick(float, float, float, float, Recti, int, Matrix4f) for details.
- * </p>
- * @param x the center x-component of a picking region in window coordinates
- * @param y the center y-component of a picking region in window coordinates
- * @param deltaX the width of the picking region in window coordinates.
- * @param deltaY the height of the picking region in window coordinates.
- * @param viewport Rect4i viewport vector
- */
- public final void gluPickMatrix(final float x, final float y,
- final float deltaX, final float deltaY, final Recti viewport) {
- if( null != mat4Tmp1.setToPick(x, y, deltaX, deltaY, viewport, mat4Tmp2) ) {
- glMultMatrixf( mat4Tmp1 );
- }
- }
-
- /**
* Map two window coordinates w/ shared X/Y and distinctive Z
* to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i>
* using a {@link AABBox#getRayIntersection(Vec3f, Ray, float, boolean) bounding box}.
@@ -1065,40 +1079,88 @@ public final class PMVMatrix implements GLMatrixFunc {
*/
public final boolean gluUnProjectRay(final float winx, final float winy, final float winz0, final float winz1,
final Recti viewport, final Ray ray) {
- return Matrix4f.mapWinToRay(winx, winy, winz0, winz1, matMv, matP, viewport, ray, mat4Tmp1, mat4Tmp2);
+ return Matrix4f.mapWinToRay(winx, winy, winz0, winz1, getPMviMat(), viewport, ray);
+ }
+
+ /**
+ * Make given matrix the <i>pick</i> matrix based on given parameters.
+ * <p>
+ * Traditional <code>gluPickMatrix</code> implementation.
+ * </p>
+ * <p>
+ * See {@link Matrix4f#setToPick(float, float, float, float, Recti, int, Matrix4f) for details.
+ * </p>
+ * @param x the center x-component of a picking region in window coordinates
+ * @param y the center y-component of a picking region in window coordinates
+ * @param deltaX the width of the picking region in window coordinates.
+ * @param deltaY the height of the picking region in window coordinates.
+ * @param viewport Rect4i viewport vector
+ */
+ public final void gluPickMatrix(final float x, final float y,
+ final float deltaX, final float deltaY, final Recti viewport) {
+ if( null != mat4Tmp1.setToPick(x, y, deltaX, deltaY, viewport, getTmp2Mat()) ) {
+ glMultMatrixf( mat4Tmp1 );
+ }
}
public StringBuilder toString(StringBuilder sb, final String f) {
if(null == sb) {
sb = new StringBuilder();
}
- final boolean mviDirty = 0 != (DIRTY_INVERSE_MODELVIEW & dirtyBits);
- final boolean mvitDirty = 0 != (DIRTY_INVERSE_TRANSPOSED_MODELVIEW & dirtyBits);
- final boolean frustumDirty = 0 != (DIRTY_FRUSTUM & dirtyBits);
- final boolean mviReq = 0 != (DIRTY_INVERSE_MODELVIEW & requestMask);
- final boolean mvitReq = 0 != (DIRTY_INVERSE_TRANSPOSED_MODELVIEW & requestMask);
- final boolean frustumReq = 0 != (DIRTY_FRUSTUM & requestMask);
+ final boolean pmvDirty = 0 != (PREMUL_PMV & dirtyBits);
+ final boolean pmvUsed = null != matPMv;
+
+ final boolean pmviDirty = 0 != (PREMUL_PMVI & dirtyBits);
+ final boolean pmviUsed = null != matPMvi;
+
+ final boolean frustumDirty = 0 != (FRUSTUM & dirtyBits);
+ final boolean frustumUsed = null != frustum;
+
+ final boolean mviDirty = 0 != (INVERSE_MODELVIEW & dirtyBits);
+ final boolean mviReq = 0 != (INVERSE_MODELVIEW & requestBits);
+
+ final boolean mvitDirty = 0 != (INVERSE_TRANSPOSED_MODELVIEW & dirtyBits);
+ final boolean mvitReq = 0 != (INVERSE_TRANSPOSED_MODELVIEW & requestBits);
+
final boolean modP = 0 != ( MODIFIED_PROJECTION & modifiedBits );
final boolean modMv = 0 != ( MODIFIED_MODELVIEW & modifiedBits );
final boolean modT = 0 != ( MODIFIED_TEXTURE & modifiedBits );
+ int count = 3; // P, Mv, T
sb.append("PMVMatrix[modified[P ").append(modP).append(", Mv ").append(modMv).append(", T ").append(modT);
- sb.append("], dirty/req[Mvi ").append(mviDirty).append("/").append(mviReq).append(", Mvit ").append(mvitDirty).append("/").append(mvitReq).append(", Frustum ").append(frustumDirty).append("/").append(frustumReq).append("]").append(PlatformPropsImpl.NEWLINE);
+ sb.append("], dirty/used[PMv ").append(pmvDirty).append("/").append(pmvUsed).append(", Pmvi ").append(pmviDirty).append("/").append(pmviUsed).append(", Frustum ").append(frustumDirty).append("/").append(frustumUsed);
+ sb.append("], dirty/req[Mvi ").append(mviDirty).append("/").append(mviReq).append(", Mvit ").append(mvitDirty).append("/").append(mvitReq).append("]").append(PlatformPropsImpl.NEWLINE);
sb.append(", Projection").append(PlatformPropsImpl.NEWLINE);
matP.toString(sb, null, f);
sb.append(", Modelview").append(PlatformPropsImpl.NEWLINE);
matMv.toString(sb, null, f);
sb.append(", Texture").append(PlatformPropsImpl.NEWLINE);
matTex.toString(sb, null, f);
- if( 0 != ( requestMask & DIRTY_INVERSE_MODELVIEW ) ) {
+ if( null != matPMv ) {
+ sb.append(", P * Mv").append(PlatformPropsImpl.NEWLINE);
+ matPMv.toString(sb, null, f);
+ ++count;
+ }
+ if( null != matPMvi ) {
+ sb.append(", P * Mv").append(PlatformPropsImpl.NEWLINE);
+ matPMvi.toString(sb, null, f);
+ ++count;
+ }
+ if( mviReq ) {
sb.append(", Inverse Modelview").append(PlatformPropsImpl.NEWLINE);
matMvi.toString(sb, null, f);
+ ++count;
}
- if( 0 != ( requestMask & DIRTY_INVERSE_TRANSPOSED_MODELVIEW ) ) {
+ if( mvitReq ) {
sb.append(", Inverse Transposed Modelview").append(PlatformPropsImpl.NEWLINE);
matMvit.toString(sb, null, f);
+ ++count;
}
- sb.append("]");
+ int tmpCount = 1;
+ if( null != mat4Tmp2 ) {
+ ++tmpCount;
+ }
+ sb.append(", matrices "+count+" + "+tmpCount+" temp = "+(count+tmpCount)+"]");
return sb;
}
@@ -1118,6 +1180,8 @@ public final class PMVMatrix implements GLMatrixFunc {
* @see #MODIFIED_PROJECTION
* @see #MODIFIED_MODELVIEW
* @see #MODIFIED_TEXTURE
+ * @see #getDirtyBits()
+ * @see #isReqDirty()
*/
public final int getModifiedBits(final boolean clear) {
final int r = modifiedBits;
@@ -1128,21 +1192,28 @@ public final class PMVMatrix implements GLMatrixFunc {
}
/**
- * Returns the dirty bits due to mutable operations.
+ * Returns the dirty bits due to mutable operations,
+ * i.e.
+ * - {@link #INVERSE_MODELVIEW} (if requested)
+ * - {@link #INVERSE_TRANSPOSED_MODELVIEW} (if requested)
+ * - {@link #FRUSTUM} (always, cleared via {@link #getFrustum()}
* <p>
- * A dirty bit is set , if the corresponding matrix had been modified by a mutable operation
- * since last {@link #update()} call. The latter clears the dirty state only if the dirty matrix (Mvi or Mvit) or {@link Frustum}
- * has been requested by one of the {@link #getMviMat() Mvi get}, {@link #getMvitMat() Mvit get}
- * or {@link #getFrustum() Frustum get} methods.
+ * A dirty bit is set, if the corresponding matrix had been modified by a mutable operation
+ * since last {@link #update()} call and requested in the constructor {@link #PMVMatrix(int)}.
+ * </p>
+ * <p>
+ * {@link #update()} clears the dirty state for the matrices and {@link #getFrustum()} for {@link #FRUSTUM}.
* </p>
*
- * @see #DIRTY_INVERSE_MODELVIEW
- * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW
- * @see #DIRTY_FRUSTUM
+ * @see #isReqDirty()
+ * @see #INVERSE_MODELVIEW
+ * @see #INVERSE_TRANSPOSED_MODELVIEW
+ * @see #FRUSTUM
+ * @see #PMVMatrix(int)
* @see #getMviMat()
* @see #getMvitMat()
- * @see #glGetPMvMviMatrixf()
- * @see #glGetPMvMvitMatrixf()
+ * @see #getSyncPMvMviMat()
+ * @see #getSyncPMvMviMvitMat()
* @see #getFrustum()
*/
public final int getDirtyBits() {
@@ -1150,162 +1221,237 @@ public final class PMVMatrix implements GLMatrixFunc {
}
/**
- * Returns the request bit mask, which uses bit values equal to the dirty mask.
+ * Returns true if the one of the {@link #getReqBits() requested bits} are are set dirty due to mutable operations,
+ * i.e. at least one of
+ * - {@link #INVERSE_MODELVIEW}
+ * - {@link #INVERSE_TRANSPOSED_MODELVIEW}
+ * <p>
+ * A dirty bit is set, if the corresponding matrix had been modified by a mutable operation
+ * since last {@link #update()} call and requested in the constructor {@link #PMVMatrix(int)}.
+ * </p>
* <p>
- * The request bit mask is set by one of the {@link #getMviMat() Mvi get}, {@link #getMvitMat() Mvit get}
- * or {@link #getFrustum() Frustum get} methods.
+ * {@link #update()} clears the dirty state for the matrices and {@link #getFrustum()} for {@link #FRUSTUM}.
* </p>
*
- * @see #clearAllUpdateRequests()
- * @see #DIRTY_INVERSE_MODELVIEW
- * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW
- * @see #DIRTY_FRUSTUM
+ * @see #INVERSE_MODELVIEW
+ * @see #INVERSE_TRANSPOSED_MODELVIEW
+ * @see #PMVMatrix(int)
* @see #getMviMat()
* @see #getMvitMat()
- * @see #glGetPMvMviMatrixf()
- * @see #glGetPMvMvitMatrixf()
- * @see #getFrustum()
+ * @see #getSyncPMvMviMat()
+ * @see #getSyncPMvMviMvitMat()
*/
- public final int getRequestMask() {
- return requestMask;
+ public final boolean isReqDirty() {
+ return 0 != ( requestBits & dirtyBits );
}
-
/**
- * Clears all {@link #update()} requests of the Mvi and Mvit matrix and Frustum
- * after it has been enabled by one of the {@link #getMviMat() Mvi get}, {@link #getMvitMat() Mvit get}
- * or {@link #getFrustum() Frustum get} methods.
+ * Returns the request bit mask, which uses bit values equal to the dirty mask
+ * and may contain
+ * - {@link #INVERSE_MODELVIEW}
+ * - {@link #INVERSE_TRANSPOSED_MODELVIEW}
* <p>
- * Allows user to disable subsequent Mvi, Mvit and {@link Frustum} updates if no more required.
+ * The request bit mask is set by in the constructor {@link #PMVMatrix(int)}.
* </p>
*
+ * @see #INVERSE_MODELVIEW
+ * @see #INVERSE_TRANSPOSED_MODELVIEW
+ * @see #PMVMatrix(int)
* @see #getMviMat()
* @see #getMvitMat()
- * @see #glGetPMvMviMatrixf()
- * @see #glGetPMvMvitMatrixf()
+ * @see #getSyncPMvMviMat()
+ * @see #getSyncPMvMviMvitMat()
* @see #getFrustum()
- * @see #getRequestMask()
*/
- public final void clearAllUpdateRequests() {
- requestMask &= ~DIRTY_ALL;
+ public final int getReqBits() {
+ return requestBits;
+ }
+
+ /**
+ * Returns the pre-multiplied projection x modelview, P x Mv.
+ * <p>
+ * This {@link Matrix4f} instance should be re-fetched via this method and not locally stored
+ * to have it updated from a potential modification of underlying projection and/or modelview matrix.
+ * {@link #update()} has no effect on this {@link Matrix4f}.
+ * </p>
+ * <p>
+ * This pre-multipled P x Mv is considered dirty, if its corresponding
+ * {@link #getPMat() P matrix} or {@link #getMvMat() Mv matrix} has been modified since its last update.
+ * </p>
+ * @see #update()
+ */
+ public final Matrix4f getPMvMat() {
+ if( 0 != ( dirtyBits & PREMUL_PMV ) ) {
+ if( null == matPMv ) {
+ matPMv = new Matrix4f();
+ }
+ matPMv.mul(matP, matMv);
+ dirtyBits &= ~PREMUL_PMV;
+ }
+ return matPMv;
+ }
+
+ /**
+ * Returns the pre-multiplied inverse projection x modelview,
+ * if {@link Matrix4f#invert(Matrix4f)} succeeded, otherwise `null`.
+ * <p>
+ * This {@link Matrix4f} instance should be re-fetched via this method and not locally stored
+ * to have it updated from a potential modification of underlying projection and/or modelview matrix.
+ * {@link #update()} has no effect on this {@link Matrix4f}.
+ * </p>
+ * <p>
+ * This pre-multipled invert(P x Mv) is considered dirty, if its corresponding
+ * {@link #getPMat() P matrix} or {@link #getMvMat() Mv matrix} has been modified since its last update.
+ * </p>
+ * @see #update()
+ */
+ public final Matrix4f getPMviMat() {
+ if( 0 != ( dirtyBits & PREMUL_PMVI ) ) {
+ if( null == matPMvi ) {
+ matPMvi = new Matrix4f();
+ }
+ final Matrix4f mPMv = getPMvMat();
+ matPMviOK = matPMvi.invert(mPMv);
+ dirtyBits &= ~PREMUL_PMVI;
+ }
+ return matPMviOK ? matPMvi : null;
+ }
+
+ /**
+ * Returns the frustum, derived from projection x modelview.
+ * <p>
+ * This {@link Frustum} instance should be re-fetched via this method and not locally stored
+ * to have it updated from a potential modification of underlying projection and/or modelview matrix.
+ * {@link #update()} has no effect on this {@link Frustum}.
+ * </p>
+ * <p>
+ * The {@link Frustum} is considered dirty, if its corresponding
+ * {@link #getPMat() P matrix} or {@link #getMvMat() Mv matrix} has been modified since its last update.
+ * </p>
+ * @see #update()
+ */
+ public final Frustum getFrustum() {
+ if( 0 != ( dirtyBits & FRUSTUM ) ) {
+ if( null == frustum ) {
+ frustum = new Frustum();
+ }
+ final Matrix4f mPMv = getPMvMat();
+ frustum.updateFrustumPlanes(mPMv);
+ dirtyBits &= ~FRUSTUM;
+ }
+ return frustum;
}
/**
* Update the derived {@link #getMviMat() inverse modelview (Mvi)},
- * {@link #getMvitMat() inverse transposed modelview (Mvit)} matrices and {@link Frustum}
- * <b>if</b> they are dirty <b>and</b> they were requested
- * by one of the {@link #getMviMat() Mvi get}, {@link #getMvitMat() Mvit get}
- * or {@link #getFrustum() Frustum get} methods.
+ * {@link #getMvitMat() inverse transposed modelview (Mvit)} matrices
+ * <b>if</b> they {@link #isReqDirty() are dirty} <b>and</b>
+ * requested via the constructor {@link #PMVMatrix(int)}.<br/>
+ * Hence updates the following dirty bits.
+ * - {@link #INVERSE_MODELVIEW}
+ * - {@link #INVERSE_TRANSPOSED_MODELVIEW}
* <p>
- * The Mvi and Mvit matrices and {@link Frustum} are considered dirty, if their corresponding
+ * The {@link Frustum} is updated only via {@link #getFrustum()} separately.
+ * </p>
+ * <p>
+ * The Mvi and Mvit matrices are considered dirty, if their corresponding
* {@link #getMvMat() Mv matrix} has been modified since their last update.
* </p>
* <p>
- * Method should be called manually in case mutable operations has been called
+ * Method is automatically called by {@link SyncMatrix4f} and {@link SyncMatrices4f}
+ * instances {@link SyncAction} as retrieved by e.g. {@link #getSyncMvitMat()}.
+ * This ensures an automatic update cycle if used with {@link GLUniformData}.
+ * </p>
+ * <p>
+ * Method may be called manually in case mutable operations has been called
* and caller operates on already fetched references, i.e. not calling
- * {@link #getMviMat() Mvi get}, {@link #getMvitMat() Mvit get}
- * or {@link #getFrustum() Frustum get} etc anymore.
+ * {@link #getMviMat()}, {@link #getMvitMat()} anymore.
* </p>
* <p>
- * This method clears the modified bits like {@link #getModifiedBits(boolean) getModifiedBits(true)},
+ * Method clears the modified bits like {@link #getModifiedBits(boolean) getModifiedBits(true)},
* which are set by any mutable operation. The modified bits have no impact
* on this method, but the return value.
* </p>
*
* @return true if any matrix has been modified since last update call or
- * if the derived matrices Mvi and Mvit or {@link Frustum} were updated, otherwise false.
+ * if the derived matrices Mvi and Mvit were updated, otherwise false.
* In other words, method returns true if any matrix used by the caller must be updated,
* e.g. uniforms in a shader program.
*
* @see #getModifiedBits(boolean)
- * @see #MODIFIED_PROJECTION
- * @see #MODIFIED_MODELVIEW
- * @see #MODIFIED_TEXTURE
- * @see #DIRTY_INVERSE_MODELVIEW
- * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW
- * @see #DIRTY_FRUSTUM
+ * @see #isReqDirty()
+ * @see #INVERSE_MODELVIEW
+ * @see #INVERSE_TRANSPOSED_MODELVIEW
+ * @see #PMVMatrix(int)
* @see #getMviMat()
* @see #getMvitMat()
- * @see #glGetPMvMviMatrixf()
- * @see #glGetPMvMvitMatrixf()
- * @see #getFrustum()
- * @see #clearAllUpdateRequests()
+ * @see #getSyncPMvMviMat()
+ * @see #getSyncPMvMviMvitMat()
*/
public final boolean update() {
return updateImpl(true);
}
- private final boolean updateImpl(final boolean clearModBits) {
- boolean mod = 0 != modifiedBits;
- if(clearModBits) {
- modifiedBits = 0;
- }
-
- if( 0 != ( dirtyBits & ( DIRTY_FRUSTUM & requestMask ) ) ) {
- if( null == frustum ) {
- frustum = new Frustum();
- }
- mat4Tmp1.mul(matP, matMv);
- frustum.updateFrustumPlanes(mat4Tmp1);
- dirtyBits &= ~DIRTY_FRUSTUM;
- mod = true;
- }
-
- if( 0 == ( dirtyBits & requestMask ) ) {
- return mod; // nothing more requested which may have been dirty
- }
-
- return setMviMvit() || mod;
- }
//
// private
//
- private static final String msgCantComputeInverse = "Invalid source Mv matrix, can't compute inverse";
- private final boolean setMviMvit() {
- boolean res = false;
- if( 0 != ( dirtyBits & DIRTY_INVERSE_MODELVIEW ) ) { // only if dirt; always requested at this point, see update()
+ private final boolean updateImpl(final boolean clearModBits) {
+ boolean mod = 0 != modifiedBits;
+ if( clearModBits ) {
+ modifiedBits = 0;
+ }
+ if( 0 != ( requestBits & ( ( dirtyBits & ( INVERSE_MODELVIEW | INVERSE_TRANSPOSED_MODELVIEW ) ) ) ) ) { // only if dirt requested & dirty
if( !matMvi.invert(matMv) ) {
throw new GLException(msgCantComputeInverse);
}
- dirtyBits &= ~DIRTY_INVERSE_MODELVIEW;
- res = true;
+ dirtyBits &= ~INVERSE_MODELVIEW;
+ mod = true;
}
- if( 0 != ( requestMask & ( dirtyBits & DIRTY_INVERSE_TRANSPOSED_MODELVIEW ) ) ) { // only if requested & dirty
+ if( 0 != ( requestBits & ( dirtyBits & INVERSE_TRANSPOSED_MODELVIEW ) ) ) { // only if requested & dirty
matMvit.transpose(matMvi);
- dirtyBits &= ~DIRTY_INVERSE_TRANSPOSED_MODELVIEW;
- res = true;
+ dirtyBits &= ~INVERSE_TRANSPOSED_MODELVIEW;
+ mod = true;
}
- return res;
+ return mod;
}
+ private static final String msgCantComputeInverse = "Invalid source Mv matrix, can't compute inverse";
private final Matrix4f matP;
private final Matrix4f matMv;
+ private final Matrix4f matTex;
+
private final Matrix4f matMvi;
private final Matrix4f matMvit;
- private final Matrix4f matTex;
private static final int mP_offset = 0*16;
private static final int mMv_offset = 1*16;
- private static final int mMvi_offset = 2*16;
- private static final int mMvit_offset = 3*16;
- private static final int mTex_offset = 4*16;
+ private final int mMvi_offset;
+ private final int mMvit_offset;
+ private final int mTex_offset;
private final float[] matrixStore;
- private final FloatBuffer matrixP, matrixMv, matrixMvi, matrixMvit, matrixTex;
- private final FloatBuffer matrixPMvMvit, matrixPMvMvi, matrixPMv;
- private final SyncMatrix4f matPSync, matMvSync, matMviSync, matMvitSync, matTexSync;
- private final SyncMatrices4f matPMvMvitSync, matPMvMviSync, matPMvSync;
+ private final FloatBuffer bufP, bufMv, bufTex;
+ private final FloatBuffer bufMvi, bufMvit;
+ private final FloatBuffer bufP_Mv, bufP_Mv_Mvi, bufP_Mv_Mvi_Mvit;
- private final Matrix4f mat4Tmp1, mat4Tmp2;
+ private final SyncMatrix4f syncP, syncMv, syncT;
+ private final SyncMatrix4f syncMvi, syncMvit;
+ private final SyncMatrices4f syncP_Mv, syncP_Mv_Mvi, syncP_Mv_Mvi_Mvit;
+
+ private final Matrix4f mat4Tmp1;
private final Vec3f vec3Tmp1;
private final Vec4f vec4Tmp1;
private int matrixMode = GL_MODELVIEW;
private int modifiedBits = MODIFIED_ALL;
- private int dirtyBits = DIRTY_ALL; // contains the dirty bits, i.e. hinting for update operation
- private int requestMask = 0; // may contain the requested dirty bits: DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW
+ private int dirtyBits = 0; // contains the dirty bits, i.e. hinting for update operation
+ private final int requestBits; // may contain the requested bits: INVERSE_MODELVIEW | INVERSE_TRANSPOSED_MODELVIEW
+ private Matrix4f mat4Tmp2;
+ private Matrix4f matPMv;
+ private Matrix4f matPMvi;
+ private boolean matPMviOK;
private Frustum frustum;
private abstract class PMVSyncBuffer implements SyncMatrix4f {
@@ -1359,42 +1505,88 @@ public final class PMVMatrix implements GLMatrixFunc {
@Override
public SyncAction getAction() { return action; }
}
- private final class SyncBufferN implements SyncMatrices4f {
- private final Matrix4f[] mats;
- private final FloatBuffer fbuf;
+ private final class SyncBuffer1U extends PMVSyncBuffer {
private final int offset;
private final SyncAction action = new SyncAction() {
@Override
public void sync() {
- int ioff = offset;
- for(int i=0; i<mats.length; ++i, ioff+=16) {
- mats[i].get(matrixStore, ioff);
- }
+ updateImpl(true);
+ mat.get(matrixStore, offset);
}
};
- public SyncBufferN(final Matrix4f[] ms, final FloatBuffer fbuf, final int offset) {
- this.mats = ms;
- this.fbuf = fbuf;
+ public SyncBuffer1U(final Matrix4f m, final FloatBuffer fbuf, final int offset) {
+ super(m, fbuf);
this.offset = offset;
}
@Override
public SyncAction getAction() { return action; }
+ }
+
+ private abstract class PMVSyncBufferN implements SyncMatrices4f {
+ protected final Matrix4f[] mats;
+ private final FloatBuffer fbuf;
+
+ public PMVSyncBufferN(final Matrix4f[] ms, final FloatBuffer fbuf) {
+ this.mats = ms;
+ this.fbuf = fbuf;
+ }
@Override
- public Buffer getBuffer() { return fbuf; }
+ public final Buffer getBuffer() { return fbuf; }
@Override
- public SyncBuffer sync() { getAction().sync(); return this; }
+ public final SyncBuffer sync() { getAction().sync(); return this; }
@Override
- public Buffer getSyncBuffer() { getAction().sync(); return fbuf; }
+ public final Buffer getSyncBuffer() { getAction().sync(); return fbuf; }
@Override
public Matrix4f[] getMatrices() { return mats; }
@Override
- public FloatBuffer getSyncFloats() { getAction().sync(); return fbuf; }
+ public final FloatBuffer getSyncFloats() { getAction().sync(); return fbuf; }
+ }
+ private final class SyncBufferN extends PMVSyncBufferN {
+ private final int offset;
+ private final SyncAction action = new SyncAction() {
+ @Override
+ public void sync() {
+ int ioff = offset;
+ for(int i=0; i<mats.length; ++i, ioff+=16) {
+ mats[i].get(matrixStore, ioff);
+ }
+ }
+ };
+
+ public SyncBufferN(final Matrix4f[] ms, final FloatBuffer fbuf, final int offset) {
+ super(ms, fbuf);
+ this.offset = offset;
+ }
+
+ @Override
+ public SyncAction getAction() { return action; }
+ }
+ private final class SyncBufferNU extends PMVSyncBufferN {
+ private final int offset;
+ private final SyncAction action = new SyncAction() {
+ @Override
+ public void sync() {
+ updateImpl(true);
+ int ioff = offset;
+ for(int i=0; i<mats.length; ++i, ioff+=16) {
+ mats[i].get(matrixStore, ioff);
+ }
+ }
+ };
+
+ public SyncBufferNU(final Matrix4f[] ms, final FloatBuffer fbuf, final int offset) {
+ super(ms, fbuf);
+ this.offset = offset;
+ }
+
+ @Override
+ public SyncAction getAction() { return action; }
}
}