From a644d779ab19cb1d200ae4ba567b9c042c34b337 Mon Sep 17 00:00:00 2001
From: Sven Gothel
+ * Further more, PMVMatrix provides the {@link #glGetMviMatrixf() inverse modelview matrix (Mvi)} and
+ * {@link #glGetMvitMatrixf() inverse transposed modelview matrix (Mvit)}.
+ * To keep both synchronized after mutable Mv operations like {@link #glRotatef(float, float, float, float) glRotatef(..)}
+ * in {@link #glMatrixMode(int) glMatrixMode}({@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}),
+ * users have to call {@link #update()} before using Mvi and Mvit.
+ *
+ * All matrices are provided in column-major order,
+ * as specified in the OpenGL fixed function pipeline, i.e. compatibility profile.
+ *
+ * PMVMatrix can supplement {@link GL2ES2} applications w/ the
+ * lack of the described matrix functionality.
+ *
+ * All matrices use a common FloatBuffer storage
+ * and are a {@link Buffers#slice2Float(Buffer, float[], int, int) sliced} representation of it.
+ * The common FloatBuffer and hence all matrices may use NIO direct storage or a {@link #usesBackingArray() backing float array},
+ * depending how the instance if {@link #PMVMatrix(boolean) being constructed}.
+ *
+ * Note:
+ * Matrix storage details
+ *
+ *
+ *
useBackingArray = true
.
@@ -132,13 +317,16 @@ public class PMVMatrix implements GLMatrixFunc {
glLoadIdentity();
glMatrixMode(GL.GL_TEXTURE);
glLoadIdentity();
- setDirty();
- update();
+ modifiedBits = MODIFIED_ALL;
+ dirtyBits = DIRTY_ALL;
+ requestMask = 0;
+ matrixMode = GL_MODELVIEW;
}
+ /** @see #PMVMatrix(boolean) */
public final boolean usesBackingArray() { return usesBackingArray; }
- public void destroy() {
+ public final void destroy() {
if(null!=projectFloat) {
projectFloat.destroy(); projectFloat=null;
}
@@ -169,170 +357,156 @@ public class PMVMatrix implements GLMatrixFunc {
}
}
-
- public static final boolean isMatrixModeName(final int matrixModeName) {
- switch(matrixModeName) {
- case GL_MODELVIEW_MATRIX:
- case GL_PROJECTION_MATRIX:
- case GL_TEXTURE_MATRIX:
- return true;
- }
- return false;
- }
-
- public static final int matrixModeName2MatrixGetName(final int matrixModeName) {
- switch(matrixModeName) {
- case GL_MODELVIEW:
- return GL_MODELVIEW_MATRIX;
- case GL_PROJECTION:
- return GL_PROJECTION_MATRIX;
- case GL.GL_TEXTURE:
- return GL_TEXTURE_MATRIX;
- default:
- throw new GLException("unsupported matrixName: "+matrixModeName);
- }
- }
-
- public static final boolean isMatrixGetName(final int matrixGetName) {
- switch(matrixGetName) {
- case GL_MATRIX_MODE:
- case GL_MODELVIEW_MATRIX:
- case GL_PROJECTION_MATRIX:
- case GL_TEXTURE_MATRIX:
- return true;
- }
- return false;
- }
-
- public static final int matrixGetName2MatrixModeName(final int matrixGetName) {
- switch(matrixGetName) {
- case GL_MODELVIEW_MATRIX:
- return GL_MODELVIEW;
- case GL_PROJECTION_MATRIX:
- return GL_PROJECTION;
- case GL_TEXTURE_MATRIX:
- return GL.GL_TEXTURE;
- default:
- throw new GLException("unsupported matrixGetName: "+matrixGetName);
- }
- }
-
- public void setDirty() {
- modified = DIRTY_MODELVIEW | DIRTY_PROJECTION | DIRTY_TEXTURE ;
- matrixMode = GL_MODELVIEW;
- }
-
- public int getDirtyBits() {
- return modified;
- }
-
- public boolean isDirty(final int matrixName) {
- boolean res;
- switch(matrixName) {
- case GL_MODELVIEW:
- res = (modified&DIRTY_MODELVIEW)!=0 ;
- break;
- case GL_PROJECTION:
- res = (modified&DIRTY_PROJECTION)!=0 ;
- break;
- case GL.GL_TEXTURE:
- res = (modified&DIRTY_TEXTURE)!=0 ;
- break;
- default:
- throw new GLException("unsupported matrixName: "+matrixName);
- }
- return res;
- }
-
- public boolean isDirty() {
- return modified!=0;
- }
-
- /**
- * Update the derived Mvi, Mvit and Pmv matrices
- * in case Mv or P has changed.
- *
- * @return
- */
- public boolean update() {
- if(0==modified) return false;
-
- final int res = modified;
- if( (res&DIRTY_MODELVIEW)!=0 ) {
- setMviMvit();
- }
- modified=0;
- return res!=0;
- }
-
+
+ /** Returns the current matrix-mode, one of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}. */
public final int glGetMatrixMode() {
return matrixMode;
}
+ /**
+ * Returns the {@link GLMatrixFunc#GL_TEXTURE_MATRIX texture matrix} (T).
+ * + * See matrix storage details. + *
+ */ public final FloatBuffer glGetTMatrixf() { return matrixTex; } + /** + * Returns the {@link GLMatrixFunc#GL_PROJECTION_MATRIX projection matrix} (P). + *+ * See matrix storage details. + *
+ */ public final FloatBuffer glGetPMatrixf() { return matrixP; } + /** + * Returns the {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mv). + *+ * See matrix storage details. + *
+ */ public final FloatBuffer glGetMvMatrixf() { return matrixMv; } - public final FloatBuffer glGetPMvMviMatrixf() { - usesMviMvit |= 1; - return matrixPMvMvi; + /** + * Returns the inverse {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvi). + *+ * Method enables the Mvi matrix update, and performs it's update w/o clearing the modified bits. + *
+ *+ * See {@link #update()} and matrix storage details. + *
+ * @see #update() + * @see #disableMviMvitUpdate() + */ + public final FloatBuffer glGetMviMatrixf() { + requestMask |= DIRTY_INVERSE_MODELVIEW ; + updateImpl(false); + return matrixMvi; } + /** + * Returns the inverse transposed {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvit). + *+ * Method enables the Mvit matrix update, and performs it's update w/o clearing the modified bits. + *
+ *+ * See {@link #update()} and matrix storage details. + *
+ * @see #update() + * @see #disableMviMvitUpdate() + */ + public final FloatBuffer glGetMvitMatrixf() { + requestMask |= DIRTY_INVERSE_TRANSPOSED_MODELVIEW ; + updateImpl(false); + return matrixMvit; + } + + /** + * Returns 2 matrices within one FloatBuffer: {@link #glGetPMatrixf() P} and {@link #glGetMvMatrixf() Mv}. + *+ * See matrix storage details. + *
+ */ public final FloatBuffer glGetPMvMatrixf() { return matrixPMv; } - public final FloatBuffer glGetMviMatrixf() { - usesMviMvit |= 1; - return matrixMvi; + /** + * Returns 3 matrices within one FloatBuffer: {@link #glGetPMatrixf() P}, {@link #glGetMvMatrixf() Mv} and {@link #glGetMviMatrixf() Mvi}. + *+ * Method enables the Mvi matrix update, and performs it's update w/o clearing the modified bits. + *
+ *+ * See {@link #update()} and matrix storage details. + *
+ * @see #update() + * @see #disableMviMvitUpdate() + */ + public final FloatBuffer glGetPMvMviMatrixf() { + requestMask |= DIRTY_INVERSE_MODELVIEW ; + updateImpl(false); + return matrixPMvMvi; } - + + /** + * Returns 4 matrices within one FloatBuffer: {@link #glGetPMatrixf() P}, {@link #glGetMvMatrixf() Mv}, {@link #glGetMviMatrixf() Mvi} and {@link #glGetMvitMatrixf() Mvit}. + *+ * Method enables the Mvi and Mvit matrix update, and performs it's update w/o clearing the modified bits. + *
+ *+ * See {@link #update()} and matrix storage details. + *
+ * @see #update() + * @see #disableMviMvitUpdate() + */ public final FloatBuffer glGetPMvMvitMatrixf() { - usesMviMvit |= 1 | 2; + requestMask |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ; + updateImpl(false); return matrixPMvMvit; } - public final FloatBuffer glGetMvitMatrixf() { - usesMviMvit |= 1 | 2; - return matrixMvit; - } - - /* - * @return the current matrix - */ + /* + * @return the matrix of the current matrix-mode + */ public final FloatBuffer glGetMatrixf() { return glGetMatrixf(matrixMode); } - /** - * @param matrixName GL_MODELVIEW, GL_PROJECTION or GL.GL_TEXTURE - * @return the given matrix - */ + /** + * @param matrixName Either a matrix-get-name, i.e. + * {@link GLMatrixFunc#GL_MODELVIEW_MATRIX GL_MODELVIEW_MATRIX}, {@link GLMatrixFunc#GL_PROJECTION_MATRIX GL_PROJECTION_MATRIX} or {@link GLMatrixFunc#GL_TEXTURE_MATRIX GL_TEXTURE_MATRIX}, + * or a matrix-mode-name, i.e. + * {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE} + * @return the named matrix + */ public final FloatBuffer glGetMatrixf(final int matrixName) { - if(matrixName==GL_MODELVIEW) { - return matrixMv; - } else if(matrixName==GL_PROJECTION) { - return matrixP; - } else if(matrixName==GL.GL_TEXTURE) { - return matrixTex; - } else { - throw new GLException("unsupported matrixName: "+matrixName); - } + switch(matrixName) { + case GL_MODELVIEW_MATRIX: + case GL_MODELVIEW: + return matrixMv; + case GL_PROJECTION_MATRIX: + case GL_PROJECTION: + return matrixP; + case GL_TEXTURE_MATRIX: + case GL.GL_TEXTURE: + return matrixTex; + default: + throw new GLException("unsupported matrixName: "+matrixName); + } } // - // MatrixIf + // GLMatrixFunc implementation // - public void glMatrixMode(final int matrixName) { + @Override + public final void glMatrixMode(final int matrixName) { switch(matrixName) { case GL_MODELVIEW: case GL_PROJECTION: @@ -344,27 +518,32 @@ public class PMVMatrix implements GLMatrixFunc { matrixMode = matrixName; } - public void glGetFloatv(int matrixGetName, FloatBuffer params) { + @Override + public final void glGetFloatv(int matrixGetName, FloatBuffer params) { int pos = params.position(); if(matrixGetName==GL_MATRIX_MODE) { params.put((float)matrixMode); } else { - FloatBuffer matrix = glGetMatrixf(matrixGetName2MatrixModeName(matrixGetName)); + FloatBuffer matrix = glGetMatrixf(matrixGetName); params.put(matrix); // matrix -> params matrix.reset(); } params.position(pos); } - public void glGetFloatv(int matrixGetName, float[] params, int params_offset) { + + @Override + public final void glGetFloatv(int matrixGetName, float[] params, int params_offset) { if(matrixGetName==GL_MATRIX_MODE) { params[params_offset]=(float)matrixMode; } else { - FloatBuffer matrix = glGetMatrixf(matrixGetName2MatrixModeName(matrixGetName)); + FloatBuffer matrix = glGetMatrixf(matrixGetName); matrix.get(params, params_offset, 16); // matrix -> params matrix.reset(); } } - public void glGetIntegerv(int pname, IntBuffer params) { + + @Override + public final void glGetIntegerv(int pname, IntBuffer params) { int pos = params.position(); if(pname==GL_MATRIX_MODE) { params.put(matrixMode); @@ -373,7 +552,9 @@ public class PMVMatrix implements GLMatrixFunc { } params.position(pos); } - public void glGetIntegerv(int pname, int[] params, int params_offset) { + + @Override + public final void glGetIntegerv(int pname, int[] params, int params_offset) { if(pname==GL_MATRIX_MODE) { params[params_offset]=matrixMode; } else { @@ -381,41 +562,46 @@ public class PMVMatrix implements GLMatrixFunc { } } + @Override public final void glLoadMatrixf(final float[] values, final int offset) { int len = values.length-offset; if(matrixMode==GL_MODELVIEW) { matrixMv.put(values, offset, len); matrixMv.reset(); - modified |= DIRTY_MODELVIEW ; + dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ; + modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { matrixP.put(values, offset, len); matrixP.reset(); - modified |= DIRTY_PROJECTION ; + modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { matrixTex.put(values, offset, len); matrixTex.reset(); - modified |= DIRTY_TEXTURE ; + modifiedBits |= MODIFIED_TEXTURE; } } + @Override public final void glLoadMatrixf(java.nio.FloatBuffer m) { int spos = m.position(); if(matrixMode==GL_MODELVIEW) { matrixMv.put(m); matrixMv.reset(); - modified |= DIRTY_MODELVIEW ; + dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ; + modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { matrixP.put(m); matrixP.reset(); - modified |= DIRTY_PROJECTION ; + modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { matrixTex.put(m); matrixTex.reset(); - modified |= DIRTY_TEXTURE ; + modifiedBits |= MODIFIED_TEXTURE; } m.position(spos); } + @Override public final void glPopMatrix() { float[] stackEntry=null; if(matrixMode==GL_MODELVIEW) { @@ -428,6 +614,7 @@ public class PMVMatrix implements GLMatrixFunc { glLoadMatrixf(stackEntry, 0); } + @Override public final void glPushMatrix() { float[] stackEntry = new float[1*16]; if(matrixMode==GL_MODELVIEW) { @@ -445,49 +632,56 @@ public class PMVMatrix implements GLMatrixFunc { } } + @Override public final void glLoadIdentity() { if(matrixMode==GL_MODELVIEW) { matrixMv.put(matrixIdent); matrixMv.reset(); - modified |= DIRTY_MODELVIEW ; + dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ; + modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { matrixP.put(matrixIdent); matrixP.reset(); - modified |= DIRTY_PROJECTION ; + modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { matrixTex.put(matrixIdent); matrixTex.reset(); - modified |= DIRTY_TEXTURE ; + modifiedBits |= MODIFIED_TEXTURE; } - matrixIdent.reset(); + matrixIdent.reset(); } + @Override public final void glMultMatrixf(final FloatBuffer m) { if(matrixMode==GL_MODELVIEW) { FloatUtil.multMatrixf(matrixMv, m, matrixMv); - modified |= DIRTY_MODELVIEW ; + dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ; + modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { FloatUtil.multMatrixf(matrixP, m, matrixP); - modified |= DIRTY_PROJECTION ; + modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { FloatUtil.multMatrixf(matrixTex, m, matrixTex); - modified |= DIRTY_TEXTURE ; + modifiedBits |= MODIFIED_TEXTURE; } } - public void glMultMatrixf(float[] m, int m_offset) { + @Override + public final void glMultMatrixf(float[] m, int m_offset) { if(matrixMode==GL_MODELVIEW) { FloatUtil.multMatrixf(matrixMv, m, m_offset, matrixMv); - modified |= DIRTY_MODELVIEW ; + dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ; + modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { FloatUtil.multMatrixf(matrixP, m, m_offset, matrixP); - modified |= DIRTY_PROJECTION ; + modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { FloatUtil.multMatrixf(matrixTex, m, m_offset, matrixTex); - modified |= DIRTY_TEXTURE ; + modifiedBits |= MODIFIED_TEXTURE; } } + @Override public final void glTranslatef(final float x, final float y, final float z) { // Translation matrix: // 1 0 0 x @@ -500,6 +694,7 @@ public class PMVMatrix implements GLMatrixFunc { glMultMatrixf(matrixTrans, 0); } + @Override public final void glRotatef(final float angdeg, float x, float y, float z) { final float angrad = angdeg * (float) Math.PI / 180.0f; final float c = (float)Math.cos(angrad); @@ -536,6 +731,7 @@ public class PMVMatrix implements GLMatrixFunc { glMultMatrixf(matrixRot, 0); } + @Override public final void glScalef(final float x, final float y, final float z) { // Scale matrix: // x 0 0 0 @@ -549,6 +745,7 @@ public class PMVMatrix implements GLMatrixFunc { glMultMatrixf(matrixScale, 0); } + @Override public final void glOrthof(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) { // Ortho matrix: // 2/dx 0 0 tx @@ -572,14 +769,7 @@ public class PMVMatrix implements GLMatrixFunc { glMultMatrixf(matrixOrtho, 0); } - public final void gluPerspective(final float fovy, final float aspect, final float zNear, final float zFar) { - float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear; - float bottom=-1.0f*top; - float left=aspect*bottom; - float right=aspect*top; - glFrustumf(left, right, bottom, top, zNear, zFar); - } - + @Override public final void glFrustumf(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) { if(zNear<=0.0f||zFar<0.0f) { throw new GLException("GL_INVALID_VALUE: zNear and zFar must be positive, and zNear>0"); @@ -614,14 +804,33 @@ public class PMVMatrix implements GLMatrixFunc { glMultMatrixf(matrixFrustum, 0); } - public void gluLookAt(float eyex, float eyey, float eyez, + // + // Extra functionality + // + + /** + * {@link #glMultMatrixf(FloatBuffer) Multiply} the {@link #glGetMatrixMode() current matrix} with the perspective/frustum matrix. + */ + public final void gluPerspective(final float fovy, final float aspect, final float zNear, final float zFar) { + float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear; + float bottom=-1.0f*top; + float left=aspect*bottom; + float right=aspect*top; + glFrustumf(left, right, bottom, top, zNear, zFar); + } + + /** + * {@link #glMultMatrixf(FloatBuffer) Multiply} and {@link #glTranslatef(float, float, float) translate} the {@link #glGetMatrixMode() current matrix} + * with the eye, object and orientation. + */ + public final void gluLookAt(float eyex, float eyey, float eyez, float centerx, float centery, float centerz, float upx, float upy, float upz) { projectFloat.gluLookAt(this, eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz); } /** - * Uses this instance {@link #glGetMvMatrixf()} and {@link #glGetPMatrixf()} + * Map object coordinates to window coordinates. * * @param objx * @param objy @@ -632,7 +841,7 @@ public class PMVMatrix implements GLMatrixFunc { * @param win_pos_offset * @return */ - public boolean gluProject(float objx, float objy, float objz, + public final boolean gluProject(float objx, float objy, float objz, int[] viewport, int viewport_offset, float[] win_pos, int win_pos_offset ) { if(usesBackingArray) { @@ -651,7 +860,7 @@ public class PMVMatrix implements GLMatrixFunc { } /** - * Uses this instance {@link #glGetMvMatrixf()} and {@link #glGetPMatrixf()} + * Map window coordinates to object coordinates. * * @param winx * @param winy @@ -680,11 +889,186 @@ public class PMVMatrix implements GLMatrixFunc { } } - public void gluPickMatrix(float x, float y, + public final void gluPickMatrix(float x, float y, float deltaX, float deltaY, int[] viewport, int viewport_offset) { projectFloat.gluPickMatrix(this, x, y, deltaX, deltaY, viewport, viewport_offset); } + + public StringBuilder toString(StringBuilder sb, 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 mviReq = 0 != (DIRTY_INVERSE_MODELVIEW & requestMask); + final boolean mvitReq = 0 != (DIRTY_INVERSE_TRANSPOSED_MODELVIEW & requestMask); + final boolean modP = 0 != ( MODIFIED_PROJECTION & modifiedBits ); + final boolean modMv = 0 != ( MODIFIED_MODELVIEW & modifiedBits ); + final boolean modT = 0 != ( MODIFIED_TEXTURE & modifiedBits ); + + sb.append("PMVMatrix[backingArray ").append(this.usesBackingArray()); + sb.append(", 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); + sb.append("], Projection").append(Platform.NEWLINE); + matrixToString(sb, f, matrixP); + sb.append(", Modelview").append(Platform.NEWLINE); + matrixToString(sb, f, matrixMv); + sb.append(", Texture").append(Platform.NEWLINE); + matrixToString(sb, f, matrixTex); + if( 0 != ( requestMask & DIRTY_INVERSE_MODELVIEW ) ) { + sb.append(", Inverse Modelview").append(Platform.NEWLINE); + matrixToString(sb, f, matrixMvi); + } + if( 0 != ( requestMask & DIRTY_INVERSE_TRANSPOSED_MODELVIEW ) ) { + sb.append(", Inverse Transposed Modelview").append(Platform.NEWLINE); + matrixToString(sb, f, matrixMvit); + } + sb.append("]"); + return sb; + } + + public String toString() { + return toString(null, "%10.5f").toString(); + } + + /** + * Returns the modified bits due to mutable operations and clears it. + *+ * A modified bit is set, if the corresponding matrix had been modified by a mutable operation + * since last {@link #update()} or {@link #getModifiedBits()} call. + *
+ * + * @see #MODIFIED_PROJECTION + * @see #MODIFIED_MODELVIEW + * @see #MODIFIED_TEXTURE + */ + public final int getModifiedBits() { + final int r = modifiedBits; + modifiedBits = 0; + return r; + } + + /** + * Returns the dirty bits due to mutable operations. + *+ * 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) + * has been requested by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods. + *
+ * + * @deprecated Function is exposed for debugging purposes only. + * @see #DIRTY_INVERSE_MODELVIEW + * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW + * @see #glGetMviMatrixf() + * @see #glGetMvitMatrixf() + * @see #glGetPMvMviMatrixf() + * @see #glGetPMvMvitMatrixf() + */ + public final int getDirtyBits() { + return dirtyBits; + } + + /** + * Returns the request bit mask, which uses bit values equal to the dirty mask. + *+ * The request bit mask is set by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods. + *
+ * + * @deprecated Function is exposed for debugging purposes only. + * @see #disableMviMvitUpdate() + * @see #DIRTY_INVERSE_MODELVIEW + * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW + * @see #glGetMviMatrixf() + * @see #glGetMvitMatrixf() + * @see #glGetPMvMviMatrixf() + * @see #glGetPMvMvitMatrixf() + */ + public final int getRequestMask() { + return requestMask; + } + + + /** + * Disable {@link #update()} of the Mvi and Mvit matrix + * after it has been enabled by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods. + *+ * This cleans the request bit mask used internally. + *
+ *+ * Function may be useful to disable subsequent Mvi and Mvit updates if no more required. + *
+ * + * @see #glGetMviMatrixf() + * @see #glGetMvitMatrixf() + * @see #glGetPMvMviMatrixf() + * @see #glGetPMvMvitMatrixf() + * @see #getRequestMask() + */ + public final void disableMviMvitUpdate() { + requestMask &= ~DIRTY_ALL; + } + + /** + * Update the derived {@link #glGetMviMatrixf() inverse modelview (Mvi)} + * and {@link #glGetMvitMatrixf() inverse transposed modelview (Mvit)} matrices + * if they are dirty and their usage/update has been requested + * by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods. + *+ * The Mvi and Mvit matrices are considered dirty, if their corresponding + * {@link #glGetMvMatrixf() Mv matrix} has been modified since their last update. + *
+ *+ * Method should be called manually in case mutable operations has been called + * and caller operates on already fetched references, i.e. not calling + * {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} etc anymore. + *
+ *+ * This method clears the modified bits like {@link #getModifiedBits()}, + * which are set by any mutable operation. The modified bits have no impact + * on this method, but the return value. + *
+ * + * @return true if any matrix has been modified since last update call or + * 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() + * @see #MODIFIED_PROJECTION + * @see #MODIFIED_MODELVIEW + * @see #MODIFIED_TEXTURE + * @see #DIRTY_INVERSE_MODELVIEW + * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW + * @see #glGetMviMatrixf() + * @see #glGetMvitMatrixf() + * @see #glGetPMvMviMatrixf() + * @see #glGetPMvMvitMatrixf() + * @see #disableMviMvitUpdate() + */ + public final boolean update() { + return updateImpl(true); + } + private final boolean updateImpl(boolean clearModBits) { + final boolean mod = 0 != modifiedBits; + if(clearModBits) { + modifiedBits = 0; + } + + if( 0 == ( dirtyBits & requestMask ) ) { + return mod; // nothing requested which may have been dirty + } + + if(nioBackupArraySupported>=0) { + try { + nioBackupArraySupported = 1; + return setMviMvitNIOBackupArray() || mod; + } catch(UnsupportedOperationException uoe) { + nioBackupArraySupported = -1; + } + } + return setMviMvitNIODirectAccess() || mod; + } // // private @@ -692,27 +1076,18 @@ public class PMVMatrix implements GLMatrixFunc { private int nioBackupArraySupported = 0; // -1 not supported, 0 - TBD, 1 - supported private final String msgCantComputeInverse = "Invalid source Mv matrix, can't compute inverse"; - private final void setMviMvit() { - if( 0 != (usesMviMvit & 1) ) { - if(nioBackupArraySupported>=0) { - try { - setMviMvitNIOBackupArray(); - nioBackupArraySupported = 1; - return; - } catch(UnsupportedOperationException uoe) { - nioBackupArraySupported = -1; - } - } - setMviMvitNIODirectAccess(); - } - } - private final void setMviMvitNIOBackupArray() { + private final boolean setMviMvitNIOBackupArray() { final float[] _matrixMvi = matrixMvi.array(); final int _matrixMviOffset = matrixMvi.position(); - if(!projectFloat.gluInvertMatrixf(matrixMv.array(), matrixMv.position(), _matrixMvi, _matrixMviOffset)) { - throw new GLException(msgCantComputeInverse); + boolean res = false; + if( 0 != ( dirtyBits & DIRTY_INVERSE_MODELVIEW ) ) { // only if dirt; always requested at this point, see update() + if(!projectFloat.gluInvertMatrixf(matrixMv.array(), matrixMv.position(), _matrixMvi, _matrixMviOffset)) { + throw new GLException(msgCantComputeInverse); + } + dirtyBits &= ~DIRTY_INVERSE_MODELVIEW; + res = true; } - if( 0 != (usesMviMvit & 2) ) { + if( 0 != ( requestMask & ( dirtyBits & DIRTY_INVERSE_TRANSPOSED_MODELVIEW ) ) ) { // only if requested & dirty // transpose matrix final float[] _matrixMvit = matrixMvit.array(); final int _matrixMvitOffset = matrixMvit.position(); @@ -721,34 +1096,43 @@ public class PMVMatrix implements GLMatrixFunc { _matrixMvit[_matrixMvitOffset+j+i*4] = _matrixMvi[_matrixMviOffset+i+j*4]; } } - } + dirtyBits &= ~DIRTY_INVERSE_TRANSPOSED_MODELVIEW; + res = true; + } + return res; } - private final void setMviMvitNIODirectAccess() { - if(!projectFloat.gluInvertMatrixf(matrixMv, matrixMvi)) { - throw new GLException(msgCantComputeInverse); + private final boolean setMviMvitNIODirectAccess() { + boolean res = false; + if( 0 != ( dirtyBits & DIRTY_INVERSE_MODELVIEW ) ) { // only if dirt; always requested at this point, see update() + if(!projectFloat.gluInvertMatrixf(matrixMv, matrixMvi)) { + throw new GLException(msgCantComputeInverse); + } + dirtyBits &= ~DIRTY_INVERSE_MODELVIEW; + res = true; } - if( 0 != (usesMviMvit & 2) ) { + if( 0 != ( requestMask & ( dirtyBits & DIRTY_INVERSE_TRANSPOSED_MODELVIEW ) ) ) { // only if requested & dirty // transpose matrix for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { matrixMvit.put(j+i*4, matrixMvi.get(i+j*4)); } } - } + dirtyBits &= ~DIRTY_INVERSE_TRANSPOSED_MODELVIEW; + res = true; + } + return res; } + protected final float[] matrixBufferArray; protected final boolean usesBackingArray; protected Buffer matrixBuffer; protected FloatBuffer matrixIdent, matrixPMvMvit, matrixPMvMvi, matrixPMv, matrixP, matrixTex, matrixMv, matrixMvi, matrixMvit; protected float[] matrixMult, matrixTrans, matrixRot, matrixScale, matrixOrtho, matrixFrustum, vec3f; protected List