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/util/PMVMatrix.java780
1 files changed, 582 insertions, 198 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
index fc6ef3ede..eb4231533 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
@@ -48,12 +48,197 @@ import jogamp.opengl.ProjectFloat;
import com.jogamp.opengl.FloatUtil;
import com.jogamp.common.nio.Buffers;
-
+import com.jogamp.common.os.Platform;
+
+/**
+ * PMVMatrix implements a subset of the fixed function pipeline
+ * regarding the projection (P), modelview (Mv) matrix operation
+ * which is specified in {@link GLMatrixFunc}.
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * All matrices are provided in column-major order,
+ * as specified in the OpenGL fixed function pipeline, i.e. compatibility profile.
+ * </p>
+ * <p>
+ * PMVMatrix can supplement {@link GL2ES2} applications w/ the
+ * lack of the described matrix functionality.
+ * </p>
+ * <a name="storageDetails"><h3>Matrix storage details</h3></a>
+ * <p>
+ * 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}.
+ * </p>
+ * <p>
+ * <b>Note:</b>
+ * <ul>
+ * <li>The matrix is a {@link Buffers#slice2Float(Buffer, float[], int, int) sliced part } of a host matrix and it's start position has been {@link FloatBuffer#mark() marked}.</li>
+ * <li>Use {@link FloatBuffer#reset() reset()} to rewind it to it's start position after relative operations, like {@link FloatBuffer#get() get()}.</li>
+ * <li>If using absolute operations like {@link FloatBuffer#get(int) get(int)}, use it's {@link FloatBuffer#reset() reset} {@link FloatBuffer#position() position} as it's offset.</li>
+ * </ul>
+ * </p>
+ */
public class PMVMatrix implements GLMatrixFunc {
- protected final float[] matrixBufferArray;
+ /** Bit value stating a modified {@link #glGetPMatrixf() projection matrix (P)}, since last {@link #update()} call. */
+ public static final int MODIFIED_PROJECTION = 1 << 0;
+ /** Bit value stating a modified {@link #glGetMvMatrixf() modelview matrix (Mv)}, since last {@link #update()} call. */
+ public static final int MODIFIED_MODELVIEW = 1 << 1;
+ /** Bit value stating a modified {@link #glGetTMatrixf() texture matrix (T)}, since last {@link #update()} call. */
+ public static final int MODIFIED_TEXTURE = 1 << 2;
+ /** Bit value stating all is modified */
+ public static final int MODIFIED_ALL = MODIFIED_PROJECTION | MODIFIED_MODELVIEW | MODIFIED_TEXTURE ;
+
+ /** Bit value stating a dirty {@link #glGetMviMatrixf() inverse modelview matrix (Mvi)}. */
+ public static final int DIRTY_INVERSE_MODELVIEW = 1 << 0;
+ /** Bit value stating a dirty {@link #glGetMvitMatrixf() inverse transposed modelview matrix (Mvit)}. */
+ public static final int DIRTY_INVERSE_TRANSPOSED_MODELVIEW = 1 << 1;
+ /** Bit value stating all is dirty */
+ public static final int DIRTY_ALL = DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
+
+ /**
+ * @param matrixModeName One of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}
+ * @return true if the given matrix-mode name is valid, otherwise false.
+ */
+ 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;
+ }
+
+ /**
+ * @param matrixModeName One of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}
+ * @return The corresponding matrix-get name, one of {@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}
+ */
+ 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);
+ }
+ }
/**
+ * @param matrixGetName One of {@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}
+ * @return true if the given matrix-get name is valid, otherwise false.
+ */
+ 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;
+ }
+
+ /**
+ * @param matrixGetName One of {@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}
+ * @return The corresponding matrix-mode name, one of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}
+ */
+ 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);
+ }
+ }
+
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param row row number
+ * @param a 4x4 matrix in column major order (OpenGL)
+ * @return matrix row string representation
+ */
+ public static StringBuilder matrixRowToString(StringBuilder sb, String f, int row, FloatBuffer a) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ final int a0 = a.position();
+ sb.append( String.format("[ "+f+" "+f+" "+f+" "+f+" ]",
+ a.get(a0+row+0*4), a.get(a0+row+1*4), a.get(a0+row+2*4), a.get(a0+row+3*4) ) );
+ return sb;
+ }
+
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param a 4x4 matrix in column major order (OpenGL)
+ * @return matrix string representation
+ */
+ public static StringBuilder matrixToString(StringBuilder sb, String f, FloatBuffer a) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ matrixRowToString(sb, f, 0, a).append(Platform.getNewline());
+ matrixRowToString(sb, f, 1, a).append(Platform.getNewline());
+ matrixRowToString(sb, f, 2, a).append(Platform.getNewline());
+ matrixRowToString(sb, f, 3, a).append(Platform.getNewline());
+ return sb;
+ }
+
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param row row number
+ * @param a 4x4 matrix in column major order (OpenGL)
+ * @param b 4x4 matrix in column major order (OpenGL)
+ * @return matrix row string representation side by side
+ */
+ public static StringBuilder matrixRowToString(StringBuilder sb, String f, int row, FloatBuffer a, FloatBuffer b) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ final int a0 = a.position();
+ final int b0 = b.position();
+ sb.append( String.format("[ "+f+" "+f+" "+f+" "+f+" =?= "+f+" "+f+" "+f+" "+f+" ]",
+ a.get(a0+row+0*4), a.get(a0+row+1*4), a.get(a0+row+2*4), a.get(a0+row+3*4),
+ b.get(b0+row+0*4), b.get(b0+row+1*4), b.get(b0+row+2*4), b.get(b0+row+3*4) ) );
+ return sb;
+ }
+
+ /**
+ * @param sb optional passed StringBuilder instance to be used
+ * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+ * @param a 4x4 matrix in column major order (OpenGL)
+ * @param b 4x4 matrix in column major order (OpenGL)
+ * @return side by side representation
+ */
+ public static StringBuilder matrixToString(StringBuilder sb, String f, FloatBuffer a, FloatBuffer b) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ matrixRowToString(sb, f, 0, a, b).append(Platform.getNewline());
+ matrixRowToString(sb, f, 1, a, b).append(Platform.getNewline());
+ matrixRowToString(sb, f, 2, a, b).append(Platform.getNewline());
+ matrixRowToString(sb, f, 3, a, b).append(Platform.getNewline());
+ return sb;
+ }
+
+ /**
* Creates an instance of PMVMatrix {@link #PMVMatrix(boolean) PMVMatrix(boolean useBackingArray)},
* with <code>useBackingArray = true</code>.
*/
@@ -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).
+ * <p>
+ * See <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ */
public final FloatBuffer glGetTMatrixf() {
return matrixTex;
}
+ /**
+ * Returns the {@link GLMatrixFunc#GL_PROJECTION_MATRIX projection matrix} (P).
+ * <p>
+ * See <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ */
public final FloatBuffer glGetPMatrixf() {
return matrixP;
}
+ /**
+ * Returns the {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mv).
+ * <p>
+ * See <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ */
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).
+ * <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 #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).
+ * <p>
+ * Method enables the Mvit 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 #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}.
+ * <p>
+ * See <a href="#storageDetails"> matrix storage details</a>.
+ * </p>
+ */
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}.
+ * <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 #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}.
+ * <p>
+ * Method enables the Mvi and Mvit 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 #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.
+ * <p>
+ * A modified bit is set, if the corresponding matrix had been modified by a mutable operation
+ * since last {@link #update()} or {@link #getModifiedBits()} call.
+ * </p>
+ *
+ * @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.
+ * <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)
+ * has been requested by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * The request bit mask is set by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * This cleans the request bit mask used internally.
+ * </p>
+ * <p>
+ * Function may be useful to disable subsequent Mvi and Mvit updates if no more required.
+ * </p>
+ *
+ * @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
+ * <b>if</b> they are dirty <b>and</b> their usage/update has been requested
+ * by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods.
+ * <p>
+ * The Mvi and Mvit matrices are considered dirty, if their corresponding
+ * {@link #glGetMvMatrixf() Mv matrix} has been modified since their last update.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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<float[]> matrixTStack, matrixPStack, matrixMvStack;
protected int matrixMode = GL_MODELVIEW;
- protected int modified = 0;
- protected int usesMviMvit = 0; // 0 - none, 1 - Mvi, 2 - Mvit, 3 - MviMvit (ofc no Mvit w/o Mvi!)
+ protected int modifiedBits = MODIFIED_ALL;
+ protected int dirtyBits = DIRTY_ALL; // contains the dirty bits, i.e. hinting for update operation
+ protected int requestMask = 0; // may contain the requested dirty bits: DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW
protected ProjectFloat projectFloat;
-
- public static final int DIRTY_MODELVIEW = 1 << 0;
- public static final int DIRTY_PROJECTION = 1 << 1;
- public static final int DIRTY_TEXTURE = 1 << 2;
}