diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java | 943 |
1 files changed, 661 insertions, 282 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..218897ffe 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java +++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2011 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -29,7 +29,7 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * */ package com.jogamp.opengl.util; @@ -37,8 +37,6 @@ package com.jogamp.opengl.util; import java.nio.Buffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; -import java.util.ArrayList; -import java.util.List; import javax.media.opengl.GL; import javax.media.opengl.GLException; @@ -46,37 +44,176 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc; import jogamp.opengl.ProjectFloat; -import com.jogamp.opengl.FloatUtil; import com.jogamp.common.nio.Buffers; - +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.FloatStack; +import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.geom.Frustum; + +/** + * 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)}. + * {@link Frustum} is also provided by {@link #glGetFrustum()}. + * To keep these derived values 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"><h5>Matrix storage details</h5></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 a dirty {@link #glGetFrustum() 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; + + /** + * @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 a 4x4 matrix in column major order (OpenGL) + * @return matrix string representation + */ + public static StringBuilder matrixToString(StringBuilder sb, String f, FloatBuffer a) { + return FloatUtil.matrixToString(sb, null, f, a, 0, 4, 4, false); + } + + /** + * @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) { + return FloatUtil.matrixToString(sb, null, f, a, 0, b, 0, 4, 4, false); + } /** * Creates an instance of PMVMatrix {@link #PMVMatrix(boolean) PMVMatrix(boolean useBackingArray)}, - * with <code>useBackingArray = true</code>. + * with <code>useBackingArray = true</code>. */ public PMVMatrix() { this(true); } - + /** * Creates an instance of PMVMatrix. - * + * * @param useBackingArray <code>true</code> for non direct NIO Buffers with guaranteed backing array, * which allows faster access in Java computation. * <p><code>false</code> for direct NIO buffers w/o a guaranteed backing array. * In most Java implementations, direct NIO buffers have no backing array - * and hence the Java computation will be throttled down by direct IO get/put - * operations.</p> + * and hence the Java computation will be throttled down by direct IO get/put + * operations.</p> * <p>Depending on the application, ie. whether the Java computation or - * JNI invocation and hence native data transfer part is heavier, + * JNI invocation and hence native data transfer part is heavier, * this flag shall be set to <code>true</code> or <code>false</code></p>. */ public PMVMatrix(boolean useBackingArray) { this.usesBackingArray = useBackingArray; - + // I Identity // T Texture // P Projection @@ -91,24 +228,24 @@ public class PMVMatrix implements GLMatrixFunc { matrixBuffer = Buffers.newDirectByteBuffer( ( 6*16 + ProjectFloat.getRequiredFloatBufferSize() ) * Buffers.SIZEOF_FLOAT ); matrixBuffer.mark(); } - + matrixIdent = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 0*16, 1*16); // I matrixTex = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 1*16, 1*16); // T - matrixPMvMvit = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 2*16, 4*16); // P + Mv + Mvi + Mvit + matrixPMvMvit = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 2*16, 4*16); // P + Mv + Mvi + Mvit matrixPMvMvi = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 2*16, 3*16); // P + Mv + Mvi matrixPMv = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 2*16, 2*16); // P + Mv matrixP = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 2*16, 1*16); // P matrixMv = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 3*16, 1*16); // Mv matrixMvi = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 4*16, 1*16); // Mvi matrixMvit = Buffers.slice2Float(matrixBuffer, matrixBufferArray, 5*16, 1*16); // Mvit - + projectFloat = new ProjectFloat(matrixBuffer, matrixBufferArray, 6*16); - + if(null != matrixBuffer) { matrixBuffer.reset(); - } + } FloatUtil.makeIdentityf(matrixIdent); - + vec3f = new float[3]; matrixMult = new float[16]; matrixTrans = new float[16]; @@ -122,8 +259,10 @@ public class PMVMatrix implements GLMatrixFunc { FloatUtil.makeIdentityf(matrixOrtho, 0); FloatUtil.makeZero(matrixFrustum, 0); - matrixPStack = new ArrayList<float[]>(); - matrixMvStack= new ArrayList<float[]>(); + // Start w/ zero size to save memory + matrixTStack = new FloatStack( 0, 2*16); // growSize: GL-min size (2) + matrixPStack = new FloatStack( 0, 2*16); // growSize: GL-min size (2) + matrixMvStack= new FloatStack( 0, 16*16); // growSize: half GL-min size (32) // default values and mode glMatrixMode(GL_PROJECTION); @@ -132,20 +271,26 @@ public class PMVMatrix implements GLMatrixFunc { glLoadIdentity(); glMatrixMode(GL.GL_TEXTURE); glLoadIdentity(); - setDirty(); - update(); + modifiedBits = MODIFIED_ALL; + dirtyBits = DIRTY_ALL; + requestMask = 0; + matrixMode = GL_MODELVIEW; + + mulPMV = null; + frustum = null; } - public final boolean usesBackingArray() { return usesBackingArray; } - - public void destroy() { + /** @see #PMVMatrix(boolean) */ + public final boolean usesBackingArray() { return usesBackingArray; } + + public final void destroy() { if(null!=projectFloat) { projectFloat.destroy(); projectFloat=null; } matrixBuffer=null; - matrixBuffer=null; matrixPMvMvit=null; matrixPMvMvi=null; matrixPMv=null; - matrixP=null; matrixTex=null; matrixMv=null; matrixMvi=null; matrixMvit=null; + matrixBuffer=null; matrixPMvMvit=null; matrixPMvMvi=null; matrixPMv=null; + matrixP=null; matrixTex=null; matrixMv=null; matrixMvi=null; matrixMvit=null; vec3f = null; matrixMult = null; @@ -154,185 +299,178 @@ public class PMVMatrix implements GLMatrixFunc { matrixScale = null; matrixOrtho = null; matrixFrustum = null; - + if(null!=matrixPStack) { - matrixPStack.clear(); matrixPStack=null; + matrixPStack=null; } if(null!=matrixMvStack) { - matrixMvStack.clear(); matrixMvStack=null; + matrixMvStack=null; } if(null!=matrixPStack) { - matrixPStack.clear(); matrixPStack=null; + matrixPStack=null; } if(null!=matrixTStack) { - matrixTStack.clear(); matrixTStack=null; - } - } - - - public static final boolean isMatrixModeName(final int matrixModeName) { - switch(matrixModeName) { - case GL_MODELVIEW_MATRIX: - case GL_PROJECTION_MATRIX: - case GL_TEXTURE_MATRIX: - return true; + matrixTStack=null; } - 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 #clearAllUpdateRequests() + */ + 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 #clearAllUpdateRequests() + */ + 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 #clearAllUpdateRequests() + */ + 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 #clearAllUpdateRequests() + */ 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; + + /** Returns the frustum, derived from projection * modelview */ + public Frustum glGetFrustum() { + requestMask |= DIRTY_FRUSTUM; + updateImpl(false); + return frustum; } - - /* - * @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 +482,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)); + final 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)); + final 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 +516,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,115 +526,131 @@ 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.put(values, offset, 16); matrixMv.reset(); - modified |= DIRTY_MODELVIEW ; + dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; + modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - matrixP.put(values, offset, len); + matrixP.put(values, offset, 16); matrixP.reset(); - modified |= DIRTY_PROJECTION ; + dirtyBits |= DIRTY_FRUSTUM ; + modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - matrixTex.put(values, offset, len); + matrixTex.put(values, offset, 16); 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 | DIRTY_FRUSTUM ; + modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { matrixP.put(m); matrixP.reset(); - modified |= DIRTY_PROJECTION ; + dirtyBits |= DIRTY_FRUSTUM ; + 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; + final FloatStack stack; if(matrixMode==GL_MODELVIEW) { - stackEntry = matrixMvStack.remove(0); + stack = matrixMvStack; } else if(matrixMode==GL_PROJECTION) { - stackEntry = matrixPStack.remove(0); + stack = matrixPStack; } else if(matrixMode==GL.GL_TEXTURE) { - stackEntry = matrixTStack.remove(0); - } - glLoadMatrixf(stackEntry, 0); + stack = matrixTStack; + } else { + throw new InternalError("XXX: mode "+matrixMode); + } + stack.position(stack.position() - 16); + glLoadMatrixf(stack.buffer(), stack.position()); } + @Override public final void glPushMatrix() { - float[] stackEntry = new float[1*16]; if(matrixMode==GL_MODELVIEW) { - matrixMv.get(stackEntry); + matrixMvStack.putOnTop(matrixMv, 16); matrixMv.reset(); - matrixMvStack.add(0, stackEntry); } else if(matrixMode==GL_PROJECTION) { - matrixP.get(stackEntry); + matrixPStack.putOnTop(matrixP, 16); matrixP.reset(); - matrixPStack.add(0, stackEntry); } else if(matrixMode==GL.GL_TEXTURE) { - matrixTex.get(stackEntry); + matrixTStack.putOnTop(matrixTex, 16); matrixTex.reset(); - matrixTStack.add(0, stackEntry); } } + @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 | DIRTY_FRUSTUM ; + modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { matrixP.put(matrixIdent); matrixP.reset(); - modified |= DIRTY_PROJECTION ; + dirtyBits |= DIRTY_FRUSTUM ; + modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { matrixTex.put(matrixIdent); matrixTex.reset(); - modified |= DIRTY_TEXTURE ; - } + modifiedBits |= MODIFIED_TEXTURE; + } matrixIdent.reset(); } + @Override public final void glMultMatrixf(final FloatBuffer m) { if(matrixMode==GL_MODELVIEW) { - FloatUtil.multMatrixf(matrixMv, m, matrixMv); - modified |= DIRTY_MODELVIEW ; + FloatUtil.multMatrixf(matrixMv, m); + dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; + modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - FloatUtil.multMatrixf(matrixP, m, matrixP); - modified |= DIRTY_PROJECTION ; + FloatUtil.multMatrixf(matrixP, m); + dirtyBits |= DIRTY_FRUSTUM ; + modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - FloatUtil.multMatrixf(matrixTex, m, matrixTex); - modified |= DIRTY_TEXTURE ; - } + FloatUtil.multMatrixf(matrixTex, m); + 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 ; + FloatUtil.multMatrixf(matrixMv, m, m_offset); + dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; + modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - FloatUtil.multMatrixf(matrixP, m, m_offset, matrixP); - modified |= DIRTY_PROJECTION ; + FloatUtil.multMatrixf(matrixP, m, m_offset); + dirtyBits |= DIRTY_FRUSTUM ; + modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - FloatUtil.multMatrixf(matrixTex, m, m_offset, matrixTex); - modified |= DIRTY_TEXTURE ; - } + FloatUtil.multMatrixf(matrixTex, m, m_offset); + modifiedBits |= MODIFIED_TEXTURE; + } } + @Override public final void glTranslatef(final float x, final float y, final float z) { - // Translation matrix: + // Translation matrix: // 1 0 0 x // 0 1 0 y // 0 0 1 z @@ -500,10 +661,11 @@ 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); - final float ic= 1.0f - c; + final float ic= 1.0f - c; final float s = (float)Math.sin(angrad); vec3f[0]=x; vec3f[1]=y; vec3f[2]=z; @@ -536,8 +698,9 @@ public class PMVMatrix implements GLMatrixFunc { glMultMatrixf(matrixRot, 0); } + @Override public final void glScalef(final float x, final float y, final float z) { - // Scale matrix: + // Scale matrix: // x 0 0 0 // 0 y 0 0 // 0 0 z 0 @@ -549,8 +712,9 @@ 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: + // Ortho matrix: // 2/dx 0 0 tx // 0 2/dy 0 ty // 0 0 2/dz tz @@ -572,14 +736,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"); @@ -587,7 +744,7 @@ public class PMVMatrix implements GLMatrixFunc { if(left==right || top==bottom) { throw new GLException("GL_INVALID_VALUE: top,bottom and left,right must not be equal"); } - // Frustum matrix: + // Frustum matrix: // 2*zNear/dx 0 A 0 // 0 2*zNear/dy B 0 // 0 0 C D @@ -614,15 +771,34 @@ 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 * @param objz @@ -632,27 +808,27 @@ 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) { return projectFloat.gluProject(objx, objy, objz, - matrixMv.array(), 0, - matrixP.array(), 0, - viewport, viewport_offset, + matrixMv.array(), matrixMv.position(), + matrixP.array(), matrixP.position(), + viewport, viewport_offset, win_pos, win_pos_offset); } else { return projectFloat.gluProject(objx, objy, objz, matrixMv, matrixP, - viewport, viewport_offset, + viewport, viewport_offset, win_pos, win_pos_offset); } } /** - * Uses this instance {@link #glGetMvMatrixf()} and {@link #glGetPMatrixf()} - * + * Map window coordinates to object coordinates. + * * @param winx * @param winy * @param winz @@ -662,58 +838,250 @@ public class PMVMatrix implements GLMatrixFunc { * @param obj_pos_offset * @return */ - public boolean gluUnProject(float winx, float winy, float winz, - int[] viewport, int viewport_offset, - float[] obj_pos, int obj_pos_offset) { + public final boolean gluUnProject(float winx, float winy, float winz, + int[] viewport, int viewport_offset, + float[] obj_pos, int obj_pos_offset) { if(usesBackingArray) { return projectFloat.gluUnProject(winx, winy, winz, - matrixMv.array(), 0, - matrixP.array(), 0, - viewport, viewport_offset, + matrixMv.array(), matrixMv.position(), + matrixP.array(), matrixP.position(), + viewport, viewport_offset, obj_pos, obj_pos_offset); } else { return projectFloat.gluUnProject(winx, winy, winz, matrixMv, matrixP, - viewport, viewport_offset, + viewport, viewport_offset, obj_pos, obj_pos_offset); - } + } } - - 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 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 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).append(", Frustum ").append(frustumDirty).append("/").append(frustumReq); + 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; + } + + @Override + public String toString() { + return toString(null, "%10.5f").toString(); + } + + /** + * Returns the modified bits due to mutable operations.. + * <p> + * A modified bit is set, if the corresponding matrix had been modified by a mutable operation + * since last {@link #update()} or {@link #getModifiedBits(boolean) getModifiedBits(true)} call. + * </p> + * @param clear if true, clears the modified bits, otherwise leaves them untouched. + * + * @see #MODIFIED_PROJECTION + * @see #MODIFIED_MODELVIEW + * @see #MODIFIED_TEXTURE + */ + public final int getModifiedBits(boolean clear) { + final int r = modifiedBits; + if(clear) { + 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) or {@link Frustum} + * has been requested by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get} + * or {@link #glGetFrustum() Frustum get} methods. + * </p> + * + * @deprecated Function is exposed for debugging purposes only. + * @see #DIRTY_INVERSE_MODELVIEW + * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW + * @see #DIRTY_FRUSTUM + * @see #glGetMviMatrixf() + * @see #glGetMvitMatrixf() + * @see #glGetPMvMviMatrixf() + * @see #glGetPMvMvitMatrixf() + * @see #glGetFrustum() + */ + 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}, {@link #glGetMvitMatrixf() Mvit get} + * or {@link #glGetFrustum() Frustum get} methods. + * </p> + * + * @deprecated Function is exposed for debugging purposes only. + * @see #clearAllUpdateRequests() + * @see #DIRTY_INVERSE_MODELVIEW + * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW + * @see #DIRTY_FRUSTUM + * @see #glGetMviMatrixf() + * @see #glGetMvitMatrixf() + * @see #glGetPMvMviMatrixf() + * @see #glGetPMvMvitMatrixf() + * @see #glGetFrustum() + */ + public final int getRequestMask() { + return requestMask; + } + + + /** + * Clears all {@link #update()} requests of the Mvi and Mvit matrix and Frustum + * after it has been enabled by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get} + * or {@link #glGetFrustum() Frustum get} methods. + * <p> + * Allows user to disable subsequent Mvi, Mvit and {@link Frustum} updates if no more required. + * </p> + * + * @see #glGetMviMatrixf() + * @see #glGetMvitMatrixf() + * @see #glGetPMvMviMatrixf() + * @see #glGetPMvMvitMatrixf() + * @see #glGetFrustum() + * @see #getRequestMask() + */ + public final void clearAllUpdateRequests() { + requestMask &= ~DIRTY_ALL; + } + + /** + * Update the derived {@link #glGetMviMatrixf() inverse modelview (Mvi)}, + * {@link #glGetMvitMatrixf() 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 #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get} + * or {@link #glGetFrustum() Frustum get} methods. + * <p> + * The Mvi and Mvit matrices and {@link Frustum} 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}, {@link #glGetMvitMatrixf() Mvit get} + * or {@link #glGetFrustum() Frustum get} etc anymore. + * </p> + * <p> + * This 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. + * 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 #glGetMviMatrixf() + * @see #glGetMvitMatrixf() + * @see #glGetPMvMviMatrixf() + * @see #glGetPMvMvitMatrixf() + * @see #glGetFrustum() + * @see #clearAllUpdateRequests() + */ + public final boolean update() { + return updateImpl(true); + } + private final boolean updateImpl(boolean clearModBits) { + boolean mod = 0 != modifiedBits; + if(clearModBits) { + modifiedBits = 0; + } + + if( 0 != ( dirtyBits & ( DIRTY_FRUSTUM & requestMask ) ) ) { + if( null == frustum ) { + frustum = new Frustum(); + mulPMV = new float[16]; + } + FloatUtil.multMatrixf(matrixP, matrixMv, mulPMV, 0); + frustum.updateByPMV(mulPMV, 0); + dirtyBits &= ~DIRTY_FRUSTUM; + mod = true; + } + + if( 0 == ( dirtyBits & requestMask ) ) { + return mod; // nothing more requested which may have been dirty + } + + if(nioBackupArraySupported>=0) { + try { + nioBackupArraySupported = 1; + return setMviMvitNIOBackupArray() || mod; + } catch(UnsupportedOperationException uoe) { + nioBackupArraySupported = -1; + } + } + return setMviMvitNIODirectAccess() || mod; + } + // - // private + // private // 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) ) { - // transpose matrix + if( 0 != ( requestMask & ( dirtyBits & DIRTY_INVERSE_TRANSPOSED_MODELVIEW ) ) ) { // only if requested & dirty + // transpose matrix final float[] _matrixMvit = matrixMvit.array(); final int _matrixMvitOffset = matrixMvit.position(); for (int i = 0; i < 4; i++) { @@ -721,34 +1089,45 @@ 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) ) { - // transpose matrix + 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 FloatStack 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; + protected float[] mulPMV; // premultiplied PMV + protected Frustum frustum; } |