diff options
Diffstat (limited to 'src/jogl/classes/com')
20 files changed, 1524 insertions, 1416 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java index a9fca4c72..4863e97d6 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -35,6 +35,7 @@ import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLES2; import com.jogamp.opengl.GLException; import com.jogamp.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.opengl.math.Recti; import jogamp.graph.curve.opengl.shader.AttributeNames; import jogamp.graph.curve.opengl.shader.UniformNames; @@ -192,25 +193,25 @@ public final class RegionRenderer { private final GLCallback enableCallback; private final GLCallback disableCallback; - private final int[] viewport = new int[] { 0, 0, 0, 0 }; + private final Recti viewport = new Recti(); private boolean initialized; private boolean vboSupported = false; public final boolean isInitialized() { return initialized; } - /** Copies the current int[4] viewport in given target and returns it for chaining. */ - public final int[/*4*/] getViewport(final int[/*4*/] target) { - System.arraycopy(viewport, 0, target, 0, 4); + /** Copies the current Rect4i viewport in given target and returns it for chaining. */ + public final Recti getViewport(final Recti target) { + target.set(viewport); return target; } - /** Borrows the current int[4] viewport w/o copying. */ - public final int[/*4*/] getViewport() { + /** Borrows the current Rect4i viewport w/o copying. */ + public final Recti getViewport() { return viewport; } /** Return width of current viewport */ - public final int getWidth() { return viewport[2]; } + public final int getWidth() { return viewport.width(); } /** Return height of current viewport */ - public final int getHeight() { return viewport[3]; } + public final int getHeight() { return viewport.height(); } /** Borrow the current {@link PMVMatrix}. */ public final PMVMatrix getMatrix() { return rs.getMatrix(); } @@ -342,10 +343,7 @@ public final class RegionRenderer { * No PMVMatrix operation is performed here. */ public final void reshapeNotify(final int x, final int y, final int width, final int height) { - viewport[0] = x; - viewport[1] = y; - viewport[2] = width; - viewport[3] = height; + viewport.set(x, y, width, height); } public final void reshapePerspective(final float angle, final int width, final int height, final float near, final float far) { diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java index aafd71d64..2f518d1cc 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java @@ -139,7 +139,7 @@ public class RenderState { public final boolean update(final GL2ES2 gl, final RenderState rs, final boolean updateLocation, final int renderModes, final boolean pass1, final boolean throwOnError) { if( rs.id() != rsId ) { // Assignment of Renderstate buffers to uniforms (no copy, direct reference) - gcu_PMVMatrix01.setData(rs.pmvMatrix.glGetPMvMatrixf()); + gcu_PMVMatrix01.setData(rs.pmvMatrix.getSyncPMvMat()); gcu_Weight.setData(rs.weightBuffer); gcu_ColorStatic.setData(rs.colorStaticBuffer); rsId = rs.id(); diff --git a/src/jogl/classes/com/jogamp/opengl/GLUniformData.java b/src/jogl/classes/com/jogamp/opengl/GLUniformData.java index 55a2e0cf1..c4cc3fe8f 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLUniformData.java +++ b/src/jogl/classes/com/jogamp/opengl/GLUniformData.java @@ -1,18 +1,52 @@ - +/** + * Copyright 2009-2023 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: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ package com.jogamp.opengl; -import java.nio.*; +import java.nio.Buffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; import com.jogamp.common.nio.Buffers; import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.util.SyncAction; +import com.jogamp.opengl.util.SyncBuffer; -public class GLUniformData { +/** + * GLSL uniform data wrapper encapsulating data to be uploaded to the GPU as a uniform. + */ +public final class GLUniformData { /** * int atom * * Number of objects is 1 * + * @param name the uniform name as used in the shader */ public GLUniformData(final String name, final int val) { initScalar(name, 1, Integer.valueOf(val)); @@ -23,6 +57,7 @@ public class GLUniformData { * * Number of objects is 1 * + * @param name the uniform name as used in the shader */ public GLUniformData(final String name, final float val) { initScalar(name, 1, Float.valueOf(val)); @@ -33,10 +68,12 @@ public class GLUniformData { * * Number of objects is calculated by data.limit()/components * + * @param name the uniform name as used in the shader * @param components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + * @param data the data */ public GLUniformData(final String name, final int components, final IntBuffer data) { - initBuffer(name, components, data); + initBuffer(name, components, data, null); } /** @@ -44,14 +81,29 @@ public class GLUniformData { * * Number of objects is calculated by data.limit()/components * + * @param name the uniform name as used in the shader * @param components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + * @param data the underlying data */ public GLUniformData(final String name, final int components, final FloatBuffer data) { - initBuffer(name, components, data); + initBuffer(name, components, data, null); + } + + /** + * Multiple IntBuffer or FloatBuffer Vector + * + * Number of objects is calculated by data.limit()/components + * + * @param name the uniform name as used in the shader + * @param components number of elements of one object, ie 4 for GL_FLOAT_VEC4, + * @param syncBuffer {@link SyncBuffer} providing {@link SyncAction} and {@link Buffer}, allowing to sync the buffer with the underlying data, see {@link #getBuffer()} + */ + public GLUniformData(final String name, final int components, final SyncBuffer syncBuffer) { + initBuffer(name, components, syncBuffer.getBuffer(), syncBuffer.getAction()); } private GLUniformData(final int components, final String name) { - initBuffer(name, components, null); + initBuffer(name, components, null, null); } public static GLUniformData creatEmptyVector(final String name, final int components) { @@ -59,7 +111,7 @@ public class GLUniformData { } public static GLUniformData creatEmptyMatrix(final String name, final int rows, final int columns) { - return new GLUniformData(name, rows, columns, null); + return new GLUniformData(name, rows, columns, (FloatBuffer)null); } /** @@ -67,17 +119,35 @@ public class GLUniformData { * * Number of objects is calculated by data.limit()/(rows*columns) * + * @param name the uniform name as used in the shader * @param rows the matrix rows * @param column the matrix column + * @param data the underlying data */ public GLUniformData(final String name, final int rows, final int columns, final FloatBuffer data) { - initBuffer(name, rows, columns, data); + initBuffer(name, rows, columns, data, null); + } + + /** + * Multiple FloatBuffer Matrix + * + * Number of objects is calculated by data.limit()/(rows*columns) + * + * @param name the uniform name as used in the shader + * @param rows the matrix rows + * @param column the matrix column + * @param syncBuffer {@link SyncBuffer} providing {@link SyncAction} and {@link Buffer}, allowing to sync the buffer with the underlying data, see {@link #getBuffer()} + */ + public GLUniformData(final String name, final int rows, final int columns, final SyncBuffer syncBuffer) { + initBuffer(name, rows, columns, syncBuffer.getBuffer(), syncBuffer.getAction()); } public GLUniformData setData(final int data) { initScalar(Integer.valueOf(data)); return this; } public GLUniformData setData(final float data) { initScalar(Float.valueOf(data)); return this; } - public GLUniformData setData(final IntBuffer data) { initBuffer(data); return this; } - public GLUniformData setData(final FloatBuffer data) { initBuffer(data); return this; } + + public GLUniformData setData(final IntBuffer data) { initBuffer(data, null); return this; } + public GLUniformData setData(final FloatBuffer data) { initBuffer(data, null); return this; } + public GLUniformData setData(final SyncBuffer syncedBuffer) { initBuffer(syncedBuffer.getBuffer(), syncedBuffer.getAction()); return this; } public int intValue() { return ((Integer)data).intValue(); }; public float floatValue() { return ((Float)data).floatValue(); }; @@ -115,16 +185,16 @@ public class GLUniformData { return toString(null).toString(); } - private void initBuffer(final String name, final int rows, final int columns, final Buffer buffer) { + private void initBuffer(final String name, final int rows, final int columns, final Buffer buffer, final SyncAction syncAction) { if( 2>rows || rows>4 || 2>columns || columns>4 ) { throw new GLException("rowsXcolumns must be within [2..4]X[2..4], is: "+rows+"X"+columns); } this.name=name; this.rows=rows; this.columns=columns; - this.isMatrix=true; + this.bits=BIT_MATRIX; this.location=-1; - initBuffer(buffer); + initBuffer(buffer, syncAction); } private void initScalar(final String name, final int components, final Object data) { if( 1>components || components>4 ) { @@ -133,27 +203,27 @@ public class GLUniformData { this.name=name; this.columns=components; this.rows=1; - this.isMatrix=false; + this.bits=0; this.location=-1; initScalar(data); } - private void initBuffer(final String name, final int components, final Buffer buffer) { + private void initBuffer(final String name, final int components, final Buffer buffer, final SyncAction syncAction) { if( 1>components || components>4 ) { throw new GLException("components must be within [1..4], is: "+components); } this.name=name; this.columns=components; this.rows=1; - this.isMatrix=false; + this.bits=0; this.location=-1; - initBuffer(buffer); + initBuffer(buffer, syncAction); } private void initScalar(final Object data) { if(data instanceof Buffer) { - initBuffer((Buffer)data); + initBuffer((Buffer)data, null); } else if( null != data ) { - if(isMatrix) { + if( isMatrix() ) { throw new GLException("Atom type not allowed for matrix : "+this); } this.count=1; @@ -164,8 +234,9 @@ public class GLUniformData { } } - private void initBuffer(final Buffer buffer) { + private void initBuffer(final Buffer buffer, final SyncAction syncAction) { if( null != buffer ) { + this.bits |= BIT_BUFFER; final int sz = rows*columns; if(buffer.remaining()<sz || 0!=buffer.remaining()%sz) { throw new GLException("remaining data buffer size invalid: buffer: "+buffer.toString()+"\n\t"+this); @@ -176,8 +247,10 @@ public class GLUniformData { this.count=0; this.data=null; } + this.syncAction = syncAction; } + /** Return the uniform name as used in the shader */ public String getName() { return name; } public int getLocation() { return location; } @@ -189,7 +262,7 @@ public class GLUniformData { public int setLocation(final int location) { this.location=location; return location; } /** - * Retrieves the location of the shader uniform from the linked shader program. + * Retrieves the location of the shader uniform with {@link #getName()} from the linked shader program. * <p> * No validation is performed within the implementation. * </p> @@ -203,26 +276,54 @@ public class GLUniformData { return location; } + /** + * Returns the data object. + * <p> + * In case a {@link SyncAction} has been set, + * it is invoked to {@link SyncAction#sync() synchronize} the object with the underlying data before returning the object. + * </p> + * @return the data object. + * @see SyncAction#sync() + */ public Object getObject() { + if( null != syncAction ) { + syncAction.sync(); + } return data; } + + /** + * Returns the data buffer. + * <p> + * In case a {@link SyncAction} has been set, + * it is invoked to {@link SyncAction#sync() synchronize} the buffer with the underlying data before returning the buffer. + * </p> + * @return the data buffer. + * @see SyncAction#sync() + */ public Buffer getBuffer() { + if( null != syncAction ) { + syncAction.sync(); + } return (data instanceof Buffer)?(Buffer)data:null; } - public boolean isBuffer() { - return (data instanceof Buffer); - } - public boolean isMatrix() { return isMatrix; } + + public boolean isMatrix() { return 0 != ( BIT_MATRIX & bits ); } + public boolean isBuffer() { return 0 != ( BIT_BUFFER & bits ); } public int count() { return count; } public int components() { return rows*columns; } public int rows() { return rows; } public int columns() { return columns; } + private static final short BIT_MATRIX = 0b0000000000000001; + private static final short BIT_BUFFER = 0b0000000000000010; + private String name; private int location; private int rows, columns; private int count; private Object data; - private boolean isMatrix; + private short bits; + private SyncAction syncAction; } diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java index 9ffa3bba6..9ef09d8c5 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java @@ -35,8 +35,6 @@ import com.jogamp.opengl.GLException; import jogamp.opengl.Debug; import com.jogamp.common.os.Platform; -import com.jogamp.opengl.math.geom.AABBox; -import com.jogamp.opengl.math.geom.Frustum; /** * Basic Float math utility functions. @@ -87,40 +85,12 @@ public final class FloatUtil { // // Matrix Ops + // Only a subset will remain here, try using Matrix4f and perhaps PMVMatrix, SyncMatrix4f16 or SyncMatrices4f16 // /** * Make matrix an identity matrix * @param m 4x4 matrix in column-major order (also result) - * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix - * @return given matrix for chaining - */ - public static float[] makeIdentity(final float[] m, final int m_offset) { - m[m_offset+0+4*0] = 1f; - m[m_offset+1+4*0] = 0f; - m[m_offset+2+4*0] = 0f; - m[m_offset+3+4*0] = 0f; - - m[m_offset+0+4*1] = 0f; - m[m_offset+1+4*1] = 1f; - m[m_offset+2+4*1] = 0f; - m[m_offset+3+4*1] = 0f; - - m[m_offset+0+4*2] = 0f; - m[m_offset+1+4*2] = 0f; - m[m_offset+2+4*2] = 1f; - m[m_offset+3+4*2] = 0f; - - m[m_offset+0+4*3] = 0f; - m[m_offset+1+4*3] = 0f; - m[m_offset+2+4*3] = 0f; - m[m_offset+3+4*3] = 1f; - return m; - } - - /** - * Make matrix an identity matrix - * @param m 4x4 matrix in column-major order (also result) * @return given matrix for chaining */ public static float[] makeIdentity(final float[] m) { @@ -159,43 +129,6 @@ public final class FloatUtil { * All matrix fields are only set if <code>initM</code> is <code>true</code>. * </p> * @param m 4x4 matrix in column-major order (also result) - * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix - * @param initM if true, given matrix will be initialized w/ identity matrix, - * otherwise only the diagonal and last-row is set. - * The latter can be utilized to share a once {@link #makeIdentity(float[], int) identity set} matrix - * for {@link #makeScale(float[], int, boolean, float, float, float) scaling} - * and {@link #makeTranslation(float[], int, boolean, float, float, float) translation}, - * while leaving the other fields untouched for performance reasons. - * @return given matrix for chaining - */ - public static float[] makeTranslation(final float[] m, final int m_offset, final boolean initM, final float tx, final float ty, final float tz) { - if( initM ) { - makeIdentity(m, m_offset); - } else { - m[m_offset+0+4*0] = 1; - m[m_offset+1+4*1] = 1; - m[m_offset+2+4*2] = 1; - m[m_offset+3+4*3] = 1; - } - m[m_offset+0+4*3] = tx; - m[m_offset+1+4*3] = ty; - m[m_offset+2+4*3] = tz; - return m; - } - - /** - * Make a translation matrix in column-major order from the given axis deltas - * <pre> - Translation matrix (Column Order): - 1 0 0 0 - 0 1 0 0 - 0 0 1 0 - x y z 1 - * </pre> - * <p> - * All matrix fields are only set if <code>initM</code> is <code>true</code>. - * </p> - * @param m 4x4 matrix in column-major order (also result) * @param initM if true, given matrix will be initialized w/ identity matrix, * otherwise only the diagonal and last-row is set. * The latter can be utilized to share a once {@link #makeIdentity(float[], int) identity set} matrix @@ -232,43 +165,6 @@ public final class FloatUtil { * All matrix fields are only set if <code>initM</code> is <code>true</code>. * </p> * @param m 4x4 matrix in column-major order (also result) - * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix - * @param initM if true, given matrix will be initialized w/ identity matrix, - * otherwise only the diagonal and last-row is set. - * The latter can be utilized to share a once {@link #makeIdentity(float[], int) identity set} matrix - * for {@link #makeScale(float[], int, boolean, float, float, float) scaling} - * and {@link #makeTranslation(float[], int, boolean, float, float, float) translation}, - * while leaving the other fields untouched for performance reasons. - * @return given matrix for chaining - */ - public static float[] makeScale(final float[] m, final int m_offset, final boolean initM, final float sx, final float sy, final float sz) { - if( initM ) { - makeIdentity(m, m_offset); - } else { - m[m_offset+0+4*3] = 0; - m[m_offset+1+4*3] = 0; - m[m_offset+2+4*3] = 0; - m[m_offset+3+4*3] = 1; - } - m[m_offset+0+4*0] = sx; - m[m_offset+1+4*1] = sy; - m[m_offset+2+4*2] = sz; - return m; - } - - /** - * Make a scale matrix in column-major order from the given axis factors - * <pre> - Scale matrix (Any Order): - x 0 0 0 - 0 y 0 0 - 0 0 z 0 - 0 0 0 1 - * </pre> - * <p> - * All matrix fields are only set if <code>initM</code> is <code>true</code>. - * </p> - * @param m 4x4 matrix in column-major order (also result) * @param initM if true, given matrix will be initialized w/ identity matrix, * otherwise only the diagonal and last-row is set. * The latter can be utilized to share a once {@link #makeIdentity(float[], int) identity set} matrix @@ -293,189 +189,6 @@ public final class FloatUtil { } /** - * Make a rotation matrix from the given axis and angle in radians. - * <pre> - Rotation matrix (Column Order): - xx(1-c)+c xy(1-c)+zs xz(1-c)-ys 0 - xy(1-c)-zs yy(1-c)+c yz(1-c)+xs 0 - xz(1-c)+ys yz(1-c)-xs zz(1-c)+c 0 - 0 0 0 1 - * </pre> - * <p> - * All matrix fields are set. - * </p> - * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a> - * @param m 4x4 matrix in column-major order (also result) - * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix - * @return given matrix for chaining - */ - public static float[] makeRotationAxis(final float[] m, final int m_offset, final float angrad, float x, float y, float z, final float[] tmpVec3f) { - final float c = cos(angrad); - final float ic= 1.0f - c; - final float s = sin(angrad); - - tmpVec3f[0]=x; tmpVec3f[1]=y; tmpVec3f[2]=z; - VectorUtil.normalizeVec3(tmpVec3f); - x = tmpVec3f[0]; y = tmpVec3f[1]; z = tmpVec3f[2]; - - final float xy = x*y; - final float xz = x*z; - final float xs = x*s; - final float ys = y*s; - final float yz = y*z; - final float zs = z*s; - m[0+0*4+m_offset] = x*x*ic+c; - m[1+0*4+m_offset] = xy*ic+zs; - m[2+0*4+m_offset] = xz*ic-ys; - m[3+0*4+m_offset] = 0; - - m[0+1*4+m_offset] = xy*ic-zs; - m[1+1*4+m_offset] = y*y*ic+c; - m[2+1*4+m_offset] = yz*ic+xs; - m[3+1*4+m_offset] = 0; - - m[0+2*4+m_offset] = xz*ic+ys; - m[1+2*4+m_offset] = yz*ic-xs; - m[2+2*4+m_offset] = z*z*ic+c; - m[3+2*4+m_offset] = 0; - - m[0+3*4+m_offset] = 0f; - m[1+3*4+m_offset] = 0f; - m[2+3*4+m_offset] = 0f; - m[3+3*4+m_offset] = 1f; - - return m; - } - - /** - * Make a concatenated rotation matrix in column-major order from the given Euler rotation angles in radians. - * <p> - * The rotations are applied in the given order: - * <ul> - * <li>y - heading</li> - * <li>z - attitude</li> - * <li>x - bank</li> - * </ul> - * </p> - * <p> - * All matrix fields are set. - * </p> - * @param m 4x4 matrix in column-major order (also result) - * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix - * @param bankX the Euler pitch angle in radians. (rotation about the X axis) - * @param headingY the Euler yaw angle in radians. (rotation about the Y axis) - * @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis) - * @return given matrix for chaining - * <p> - * Implementation does not use Quaternion and hence is exposed to - * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a> - * </p> - * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q36">Matrix-FAQ Q36</a> - * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm">euclideanspace.com-eulerToMatrix</a> - */ - public static float[] makeRotationEuler(final float[] m, final int m_offset, final float bankX, final float headingY, final float attitudeZ) { - // Assuming the angles are in radians. - final float ch = cos(headingY); - final float sh = sin(headingY); - final float ca = cos(attitudeZ); - final float sa = sin(attitudeZ); - final float cb = cos(bankX); - final float sb = sin(bankX); - - m[0+0*4+m_offset] = ch*ca; - m[1+0*4+m_offset] = sa; - m[2+0*4+m_offset] = -sh*ca; - m[3+0*4+m_offset] = 0; - - m[0+1*4+m_offset] = sh*sb - ch*sa*cb; - m[1+1*4+m_offset] = ca*cb; - m[2+1*4+m_offset] = sh*sa*cb + ch*sb; - m[3+1*4+m_offset] = 0; - - m[0+2*4+m_offset] = ch*sa*sb + sh*cb; - m[1+2*4+m_offset] = -ca*sb; - m[2+2*4+m_offset] = -sh*sa*sb + ch*cb; - m[3+2*4+m_offset] = 0; - - m[0+3*4+m_offset] = 0; - m[1+3*4+m_offset] = 0; - m[2+3*4+m_offset] = 0; - m[3+3*4+m_offset] = 1; - - return m; - } - - /** - * Make given matrix the orthogonal matrix based on given parameters. - * <pre> - Ortho matrix (Column Order): - 2/dx 0 0 0 - 0 2/dy 0 0 - 0 0 2/dz 0 - tx ty tz 1 - * </pre> - * <p> - * All matrix fields are only set if <code>initM</code> is <code>true</code>. - * </p> - * @param m 4x4 matrix in column-major order (also result) - * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix - * @param initM if true, given matrix will be initialized w/ identity matrix, - * otherwise only the orthogonal fields are set. - * @param left - * @param right - * @param bottom - * @param top - * @param zNear - * @param zFar - * @return given matrix for chaining - */ - public static float[] makeOrtho(final float[] m, final int m_offset, final boolean initM, - final float left, final float right, - final float bottom, final float top, - final float zNear, final float zFar) { - if( initM ) { - // m[m_offset+0+4*0] = 1f; - m[m_offset+1+4*0] = 0f; - m[m_offset+2+4*0] = 0f; - m[m_offset+3+4*0] = 0f; - - m[m_offset+0+4*1] = 0f; - // m[m_offset+1+4*1] = 1f; - m[m_offset+2+4*1] = 0f; - m[m_offset+3+4*1] = 0f; - - m[m_offset+0+4*2] = 0f; - m[m_offset+1+4*2] = 0f; - // m[m_offset+2+4*2] = 1f; - m[m_offset+3+4*2] = 0f; - - // m[m_offset+0+4*3] = 0f; - // m[m_offset+1+4*3] = 0f; - // m[m_offset+2+4*3] = 0f; - // m[m_offset+3+4*3] = 1f; - } - final float dx=right-left; - final float dy=top-bottom; - final float dz=zFar-zNear; - final float tx=-1.0f*(right+left)/dx; - final float ty=-1.0f*(top+bottom)/dy; - final float tz=-1.0f*(zFar+zNear)/dz; - - m[m_offset+0+4*0] = 2.0f/dx; - - m[m_offset+1+4*1] = 2.0f/dy; - - m[m_offset+2+4*2] = -2.0f/dz; - - m[m_offset+0+4*3] = tx; - m[m_offset+1+4*3] = ty; - m[m_offset+2+4*3] = tz; - m[m_offset+3+4*3] = 1f; - - return m; - } - - /** * Make given matrix the frustum matrix based on given parameters. * <pre> Frustum matrix (Column Order): @@ -699,7 +412,7 @@ public final class FloatUtil { * @param mat4Tmp temp float[16] storage * @return given matrix <code>m</code> for chaining or <code>null</code> if either delta value is <= zero. */ - public static float[] makePick(final float[] m, final int m_offset, + public static float[] makePick(final float[] m, final float x, final float y, final float deltaX, final float deltaY, final int[] viewport, final int viewport_offset, @@ -709,13 +422,13 @@ public final class FloatUtil { } /* Translate and scale the picked region to the entire window */ - makeTranslation(m, m_offset, true, + makeTranslation(m, true, (viewport[2+viewport_offset] - 2 * (x - viewport[0+viewport_offset])) / deltaX, (viewport[3+viewport_offset] - 2 * (y - viewport[1+viewport_offset])) / deltaY, 0); makeScale(mat4Tmp, true, viewport[2+viewport_offset] / deltaX, viewport[3+viewport_offset] / deltaY, 1.0f); - multMatrix(m, m_offset, mat4Tmp, 0); + multMatrix(m, mat4Tmp); return m; } @@ -723,42 +436,6 @@ public final class FloatUtil { * Transpose the given matrix. * * @param msrc 4x4 matrix in column-major order, the source - * @param msrc_offset offset in given array <i>msrc</i>, i.e. start of the 4x4 matrix - * @param mres 4x4 matrix in column-major order, the result - * @param mres_offset offset in given array <i>mres</i>, i.e. start of the 4x4 matrix - * @return given result matrix <i>mres</i> for chaining - */ - public static float[] transposeMatrix(final float[] msrc, final int msrc_offset, final float[] mres, final int mres_offset) { - mres[mres_offset+0] = msrc[msrc_offset+0*4]; - mres[mres_offset+1] = msrc[msrc_offset+1*4]; - mres[mres_offset+2] = msrc[msrc_offset+2*4]; - mres[mres_offset+3] = msrc[msrc_offset+3*4]; - - final int i4_1 = 1*4; - mres[mres_offset+0+i4_1] = msrc[msrc_offset+1+0*4]; - mres[mres_offset+1+i4_1] = msrc[msrc_offset+1+1*4]; - mres[mres_offset+2+i4_1] = msrc[msrc_offset+1+2*4]; - mres[mres_offset+3+i4_1] = msrc[msrc_offset+1+3*4]; - - final int i4_2 = 2*4; - mres[mres_offset+0+i4_2] = msrc[msrc_offset+2+0*4]; - mres[mres_offset+1+i4_2] = msrc[msrc_offset+2+1*4]; - mres[mres_offset+2+i4_2] = msrc[msrc_offset+2+2*4]; - mres[mres_offset+3+i4_2] = msrc[msrc_offset+2+3*4]; - - final int i4_3 = 3*4; - mres[mres_offset+0+i4_3] = msrc[msrc_offset+3+0*4]; - mres[mres_offset+1+i4_3] = msrc[msrc_offset+3+1*4]; - mres[mres_offset+2+i4_3] = msrc[msrc_offset+3+2*4]; - mres[mres_offset+3+i4_3] = msrc[msrc_offset+3+3*4]; - - return mres; - } - - /** - * Transpose the given matrix. - * - * @param msrc 4x4 matrix in column-major order, the source * @param mres 4x4 matrix in column-major order, the result * @return given result matrix <i>mres</i> for chaining */ @@ -792,40 +469,6 @@ public final class FloatUtil { /** * Returns the determinant of the given matrix * @param m 4x4 matrix in column-major order, the source - * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix - * @return the matrix determinant - */ - public static float matrixDeterminant(final float[] m, final int m_offset) { - float a11 = m[ 1+4*1 + m_offset ]; - float a21 = m[ 2+4*1 + m_offset ]; - float a31 = m[ 3+4*1 + m_offset ]; - float a12 = m[ 1+4*2 + m_offset ]; - float a22 = m[ 2+4*2 + m_offset ]; - float a32 = m[ 3+4*2 + m_offset ]; - float a13 = m[ 1+4*3 + m_offset ]; - float a23 = m[ 2+4*3 + m_offset ]; - float a33 = m[ 3+4*3 + m_offset ]; - - float ret = 0; - ret += m[ 0 + m_offset ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31)); - a11 = m[ 1+4*0 + m_offset ]; - a21 = m[ 2+4*0 + m_offset ]; - a31 = m[ 3+4*0 + m_offset ]; - ret -= m[ 0+4*1 + m_offset ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31)); - a12 = m[ 1+4*1 + m_offset ]; - a22 = m[ 2+4*1 + m_offset ]; - a32 = m[ 3+4*1 + m_offset ]; - ret += m[ 0+4*2 + m_offset ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31)); - a13 = m[ 1+4*2 + m_offset ]; - a23 = m[ 2+4*2 + m_offset ]; - a33 = m[ 3+4*2 + m_offset ]; - ret -= m[ 0+4*3 + m_offset ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31)); - return ret; - } - - /** - * Returns the determinant of the given matrix - * @param m 4x4 matrix in column-major order, the source * @return the matrix determinant */ public static float matrixDeterminant(final float[] m) { @@ -855,94 +498,6 @@ public final class FloatUtil { ret -= m[ 0+4*3 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31)); return ret; } - - /** - * Invert the given matrix. - * <p> - * Returns <code>null</code> if inversion is not possible, - * e.g. matrix is singular due to a bad matrix. - * </p> - * - * @param msrc 4x4 matrix in column-major order, the source - * @param msrc_offset offset in given array <i>msrc</i>, i.e. start of the 4x4 matrix - * @param mres 4x4 matrix in column-major order, the result - may be <code>msrc</code> (in-place) - * @param mres_offset offset in given array <i>mres</i>, i.e. start of the 4x4 matrix - may be <code>msrc_offset</code> (in-place) - * @return given result matrix <i>mres</i> for chaining if successful, otherwise <code>null</code>. See above. - */ - public static float[] invertMatrix(final float[] msrc, final int msrc_offset, final float[] mres, final int mres_offset) { - final float scale; - { - float max = Math.abs(msrc[0]); - - for( int i = 1; i < 16; i++ ) { - final float a = Math.abs(msrc[i]); - if( a > max ) max = a; - } - if( 0 == max ) { - return null; - } - scale = 1.0f/max; - } - - final float a11 = msrc[0+4*0+msrc_offset]*scale; - final float a21 = msrc[1+4*0+msrc_offset]*scale; - final float a31 = msrc[2+4*0+msrc_offset]*scale; - final float a41 = msrc[3+4*0+msrc_offset]*scale; - final float a12 = msrc[0+4*1+msrc_offset]*scale; - final float a22 = msrc[1+4*1+msrc_offset]*scale; - final float a32 = msrc[2+4*1+msrc_offset]*scale; - final float a42 = msrc[3+4*1+msrc_offset]*scale; - final float a13 = msrc[0+4*2+msrc_offset]*scale; - final float a23 = msrc[1+4*2+msrc_offset]*scale; - final float a33 = msrc[2+4*2+msrc_offset]*scale; - final float a43 = msrc[3+4*2+msrc_offset]*scale; - final float a14 = msrc[0+4*3+msrc_offset]*scale; - final float a24 = msrc[1+4*3+msrc_offset]*scale; - final float a34 = msrc[2+4*3+msrc_offset]*scale; - final float a44 = msrc[3+4*3+msrc_offset]*scale; - - final float m11 = + a22*(a33*a44 - a34*a43) - a23*(a32*a44 - a34*a42) + a24*(a32*a43 - a33*a42); - final float m12 = -( + a21*(a33*a44 - a34*a43) - a23*(a31*a44 - a34*a41) + a24*(a31*a43 - a33*a41)); - final float m13 = + a21*(a32*a44 - a34*a42) - a22*(a31*a44 - a34*a41) + a24*(a31*a42 - a32*a41); - final float m14 = -( + a21*(a32*a43 - a33*a42) - a22*(a31*a43 - a33*a41) + a23*(a31*a42 - a32*a41)); - final float m21 = -( + a12*(a33*a44 - a34*a43) - a13*(a32*a44 - a34*a42) + a14*(a32*a43 - a33*a42)); - final float m22 = + a11*(a33*a44 - a34*a43) - a13*(a31*a44 - a34*a41) + a14*(a31*a43 - a33*a41); - final float m23 = -( + a11*(a32*a44 - a34*a42) - a12*(a31*a44 - a34*a41) + a14*(a31*a42 - a32*a41)); - final float m24 = + a11*(a32*a43 - a33*a42) - a12*(a31*a43 - a33*a41) + a13*(a31*a42 - a32*a41); - final float m31 = + a12*(a23*a44 - a24*a43) - a13*(a22*a44 - a24*a42) + a14*(a22*a43 - a23*a42); - final float m32 = -( + a11*(a23*a44 - a24*a43) - a13*(a21*a44 - a24*a41) + a14*(a21*a43 - a23*a41)); - final float m33 = + a11*(a22*a44 - a24*a42) - a12*(a21*a44 - a24*a41) + a14*(a21*a42 - a22*a41); - final float m34 = -( + a11*(a22*a43 - a23*a42) - a12*(a21*a43 - a23*a41) + a13*(a21*a42 - a22*a41)); - final float m41 = -( + a12*(a23*a34 - a24*a33) - a13*(a22*a34 - a24*a32) + a14*(a22*a33 - a23*a32)); - final float m42 = + a11*(a23*a34 - a24*a33) - a13*(a21*a34 - a24*a31) + a14*(a21*a33 - a23*a31); - final float m43 = -( + a11*(a22*a34 - a24*a32) - a12*(a21*a34 - a24*a31) + a14*(a21*a32 - a22*a31)); - final float m44 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31); - - final float det = (a11*m11 + a12*m12 + a13*m13 + a14*m14)/scale; - if( 0 == det ) { - return null; - } - final float invdet = 1.0f / det; - - mres[0+4*0+mres_offset] = m11 * invdet; - mres[1+4*0+mres_offset] = m12 * invdet; - mres[2+4*0+mres_offset] = m13 * invdet; - mres[3+4*0+mres_offset] = m14 * invdet; - mres[0+4*1+mres_offset] = m21 * invdet; - mres[1+4*1+mres_offset] = m22 * invdet; - mres[2+4*1+mres_offset] = m23 * invdet; - mres[3+4*1+mres_offset] = m24 * invdet; - mres[0+4*2+mres_offset] = m31 * invdet; - mres[1+4*2+mres_offset] = m32 * invdet; - mres[2+4*2+mres_offset] = m33 * invdet; - mres[3+4*2+mres_offset] = m34 * invdet; - mres[0+4*3+mres_offset] = m41 * invdet; - mres[1+4*3+mres_offset] = m42 * invdet; - mres[2+4*3+mres_offset] = m43 * invdet; - mres[3+4*3+mres_offset] = m44 * invdet; - return mres; - } - /** * Invert the given matrix. * <p> @@ -1087,53 +642,6 @@ public final class FloatUtil { } /** - * Map object coordinates to window coordinates. - * <p> - * Traditional <code>gluProject</code> implementation. - * </p> - * - * @param objx - * @param objy - * @param objz - * @param mat4PMv [projection] x [modelview] matrix, i.e. P x Mv - * @param viewport 4 component viewport vector - * @param win_pos 3 component window coordinate, the result - * @param vec4Tmp1 4 component vector for temp storage - * @param vec4Tmp2 4 component vector for temp storage - * @return true if successful, otherwise false (z is 1) - */ - public static boolean mapObjToWin(final float objx, final float objy, final float objz, - final float[/*16*/] mat4PMv, - final int[] viewport, final float[] win_pos, - final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) { - vec4Tmp2[0] = objx; - vec4Tmp2[1] = objy; - vec4Tmp2[2] = objz; - vec4Tmp2[3] = 1.0f; - - // vec4Tmp1 = P * Mv * o - multMatrixVec(mat4PMv, vec4Tmp2, vec4Tmp1); - - if (vec4Tmp1[3] == 0.0f) { - return false; - } - - vec4Tmp1[3] = (1.0f / vec4Tmp1[3]) * 0.5f; - - // Map x, y and z to range 0-1 - vec4Tmp1[0] = vec4Tmp1[0] * vec4Tmp1[3] + 0.5f; - vec4Tmp1[1] = vec4Tmp1[1] * vec4Tmp1[3] + 0.5f; - vec4Tmp1[2] = vec4Tmp1[2] * vec4Tmp1[3] + 0.5f; - - // Map x,y to viewport - win_pos[0] = vec4Tmp1[0] * viewport[2] + viewport[0]; - win_pos[1] = vec4Tmp1[1] * viewport[3] + viewport[1]; - win_pos[2] = vec4Tmp1[2]; - - return true; - } - - /** * Map window coordinates to object coordinates. * <p> * Traditional <code>gluUnProject</code> implementation. @@ -1201,134 +709,6 @@ public final class FloatUtil { /** * Map window coordinates to object coordinates. * <p> - * Traditional <code>gluUnProject</code> implementation. - * </p> - * - * @param winx - * @param winy - * @param winz - * @param mat4PMvI inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv) - * @param viewport 4 component viewport vector - * @param viewport_offset - * @param obj_pos 3 component object coordinate, the result - * @param obj_pos_offset - * @param vec4Tmp1 4 component vector for temp storage - * @param vec4Tmp2 4 component vector for temp storage - * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z) - */ - public static boolean mapWinToObj(final float winx, final float winy, final float winz, - final float[/*16*/] mat4PMvI, - final int[] viewport, final int viewport_offset, - final float[] obj_pos, final int obj_pos_offset, - final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) { - vec4Tmp1[0] = winx; - vec4Tmp1[1] = winy; - vec4Tmp1[2] = winz; - vec4Tmp1[3] = 1.0f; - - // Map x and y from window coordinates - vec4Tmp1[0] = (vec4Tmp1[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; - vec4Tmp1[1] = (vec4Tmp1[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; - - // Map to range -1 to 1 - vec4Tmp1[0] = vec4Tmp1[0] * 2 - 1; - vec4Tmp1[1] = vec4Tmp1[1] * 2 - 1; - vec4Tmp1[2] = vec4Tmp1[2] * 2 - 1; - - // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2 - multMatrixVec(mat4PMvI, vec4Tmp1, vec4Tmp2); - - if (vec4Tmp2[3] == 0.0) { - return false; - } - - vec4Tmp2[3] = 1.0f / vec4Tmp2[3]; - - obj_pos[0+obj_pos_offset] = vec4Tmp2[0] * vec4Tmp2[3]; - obj_pos[1+obj_pos_offset] = vec4Tmp2[1] * vec4Tmp2[3]; - obj_pos[2+obj_pos_offset] = vec4Tmp2[2] * vec4Tmp2[3]; - - return true; - } - - /** - * Map two window coordinates to two object coordinates, - * distinguished by their z component. - * - * @param winx - * @param winy - * @param winz1 - * @param winz2 - * @param mat4PMvI inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv) - * @param viewport 4 component viewport vector - * @param viewport_offset - * @param obj1_pos 3 component object coordinate, the result for winz1 - * @param obj1_pos_offset - * @param obj2_pos 3 component object coordinate, the result for winz2 - * @param obj2_pos_offset - * @param vec4Tmp1 4 component vector for temp storage - * @param vec4Tmp2 4 component vector for temp storage - * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z) - */ - public static boolean mapWinToObj(final float winx, final float winy, final float winz1, final float winz2, - final float[/*16*/] mat4PMvI, final int[] viewport, - final Vec3f objPos1, final Vec3f objPos2, - final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) { - vec4Tmp1[0] = winx; - vec4Tmp1[1] = winy; - vec4Tmp1[3] = 1.0f; - - // Map x and y from window coordinates - vec4Tmp1[0] = (vec4Tmp1[0] - viewport[0]) / viewport[2]; - vec4Tmp1[1] = (vec4Tmp1[1] - viewport[1]) / viewport[3]; - - // Map to range -1 to 1 - vec4Tmp1[0] = vec4Tmp1[0] * 2 - 1; - vec4Tmp1[1] = vec4Tmp1[1] * 2 - 1; - - // - // winz1 - // - vec4Tmp1[2] = winz1; - vec4Tmp1[2] = vec4Tmp1[2] * 2 - 1; - - // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2 - multMatrixVec(mat4PMvI, vec4Tmp1, vec4Tmp2); - - if (vec4Tmp2[3] == 0.0) { - return false; - } - - vec4Tmp2[3] = 1.0f / vec4Tmp2[3]; - - objPos1.set( vec4Tmp2[0] * vec4Tmp2[3], - vec4Tmp2[1] * vec4Tmp2[3], - vec4Tmp2[2] * vec4Tmp2[3] ); - - // - // winz2 - // - vec4Tmp1[2] = winz2 * 2 - 1; - - // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2 - multMatrixVec(mat4PMvI, vec4Tmp1, vec4Tmp2); - - if (vec4Tmp2[3] == 0.0) { - return false; - } - - vec4Tmp2[3] = 1.0f / vec4Tmp2[3]; - - objPos2.set( vec4Tmp2[0] * vec4Tmp2[3], - vec4Tmp2[1] * vec4Tmp2[3], - vec4Tmp2[2] * vec4Tmp2[3] ); - - return true; - } - - /** - * Map window coordinates to object coordinates. - * <p> * Traditional <code>gluUnProject4</code> implementation. * </p> * @@ -1396,57 +776,6 @@ public final class FloatUtil { return true; } - - /** - * Map two window coordinates w/ shared X/Y and distinctive Z - * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i> - * using a {@link AABBox#getRayIntersection(Ray, float[]) bounding box}. - * <p> - * Notes for picking <i>winz0</i> and <i>winz1</i>: - * <ul> - * <li>see {@link #getZBufferEpsilon(int, float, float)}</li> - * <li>see {@link #getZBufferValue(int, float, float, float)}</li> - * <li>see {@link #getOrthoWinZ(float, float, float)}</li> - * </ul> - * </p> - * @param winx - * @param winy - * @param winz0 - * @param winz1 - * @param modelMatrix 4x4 modelview matrix - * @param modelMatrix_offset - * @param projMatrix 4x4 projection matrix - * @param projMatrix_offset - * @param viewport 4 component viewport vector - * @param viewport_offset - * @param ray storage for the resulting {@link Ray} - * @param mat4Tmp1 16 component matrix for temp storage - * @param mat4Tmp2 16 component matrix for temp storage - * @param vec4Tmp2 4 component vector for temp storage - * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity) - */ - public static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1, - final float[] modelMatrix, final int modelMatrix_offset, - final float[] projMatrix, final int projMatrix_offset, - final int[] viewport, - final Ray ray, - final float[/*16*/] mat4Tmp1, final float[/*16*/] mat4Tmp2, final float[/*4*/] vec4Tmp2) { - // mat4Tmp1 = P x Mv - multMatrix(projMatrix, projMatrix_offset, modelMatrix, modelMatrix_offset, mat4Tmp1, 0); - - // mat4Tmp1 = Inv(P x Mv) - if ( null == invertMatrix(mat4Tmp1, mat4Tmp1) ) { - return false; - } - if( mapWinToObj(winx, winy, winz0, winz1, mat4Tmp1, viewport, - ray.orig, ray.dir, mat4Tmp2, vec4Tmp2) ) { - ray.dir.sub(ray.orig).normalize(); - return true; - } else { - return false; - } - } - /** * Multiply matrix: [d] = [a] x [b] * @param a 4x4 matrix in column-major order @@ -1840,36 +1169,6 @@ public final class FloatUtil { * @param v_out m_in * v_in, 3-component column-vector * @return given result vector <i>v_out</i> for chaining */ - public static float[] multMatrixVec3(final float[] m_in, final int m_in_off, - final float[] v_in, final float[] v_out) { - // (one matrix row in column-major order) X (column vector) - v_out[0] = v_in[0] * m_in[0*4+m_in_off ] + v_in[1] * m_in[1*4+m_in_off ] + - v_in[2] * m_in[2*4+m_in_off ] + 1f * m_in[3*4+m_in_off ]; - - final int m_in_off_1 = 1+m_in_off; - v_out[1] = v_in[0] * m_in[0*4+m_in_off_1] + v_in[1] * m_in[1*4+m_in_off_1] + - v_in[2] * m_in[2*4+m_in_off_1] + 1f * m_in[3*4+m_in_off_1]; - - final int m_in_off_2 = 2+m_in_off; - v_out[2] = v_in[0] * m_in[0*4+m_in_off_2] + v_in[1] * m_in[1*4+m_in_off_2] + - v_in[2] * m_in[2*4+m_in_off_2] + 1f * m_in[3*4+m_in_off_2]; - - return v_out; - } - - /** - * Affine 3f-vector transformation by 4x4 matrix - * - * 4x4 matrix multiplication with 3-component vector, - * using {@code 1} for for {@code v_in[3]} and dropping {@code v_out[3]}, - * which shall be {@code 1}. - * - * @param m_in 4x4 matrix in column-major order - * @param m_in_off - * @param v_in 3-component column-vector - * @param v_out m_in * v_in, 3-component column-vector - * @return given result vector <i>v_out</i> for chaining - */ public static float[] multMatrixVec3(final float[] m_in, final float[] v_in, final float[] v_out) { // (one matrix row in column-major order) X (column vector) v_out[0] = v_in[0] * m_in[0*4 ] + v_in[1] * m_in[1*4 ] + @@ -2000,66 +1299,6 @@ public final class FloatUtil { return sb; } - /** - * @param sb optional passed StringBuilder instance to be used - * @param rowPrefix optional prefix for each row - * @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 aOffset offset to <code>a</code>'s current position - * @param b 4x4 matrix in column major order (OpenGL) - * @param bOffset offset to <code>a</code>'s current position - * @param rows - * @param columns - * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL) - * @return side by side representation - */ - public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f, - final FloatBuffer a, final int aOffset, final FloatBuffer b, final int bOffset, - final int rows, final int columns, final boolean rowMajorOrder) { - if(null == sb) { - sb = new StringBuilder(); - } - final String prefix = ( null == rowPrefix ) ? "" : rowPrefix; - for(int i=0; i<rows; i++) { - sb.append(prefix).append("[ "); - matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i); - sb.append("=?= "); - matrixRowToString(sb, f, b, bOffset, rows, columns, rowMajorOrder, i); - sb.append("]").append(Platform.getNewline()); - } - return sb; - } - - /** - * @param sb optional passed StringBuilder instance to be used - * @param rowPrefix optional prefix for each row - * @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 aOffset offset to <code>a</code>'s current position - * @param b 4x4 matrix in column major order (OpenGL) - * @param bOffset offset to <code>a</code>'s current position - * @param rows - * @param columns - * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL) - * @return side by side representation - */ - public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f, - final float[] a, final int aOffset, final float[] b, final int bOffset, - final int rows, final int columns, final boolean rowMajorOrder) { - if(null == sb) { - sb = new StringBuilder(); - } - final String prefix = ( null == rowPrefix ) ? "" : rowPrefix; - for(int i=0; i<rows; i++) { - sb.append(prefix).append("[ "); - matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i); - sb.append("=?= "); - matrixRowToString(sb, f, b, bOffset, rows, columns, rowMajorOrder, i); - sb.append("]").append(Platform.getNewline()); - } - return sb; - } - // // Scalar Ops // diff --git a/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java b/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java index 6f4b2f38d..a06d5cefc 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java +++ b/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java @@ -121,10 +121,44 @@ public class Matrix4f { load(m, m_off); } + /** + * Creates a new matrix based on given {@link FloatBuffer} 4x4 column major order. + * @param m 4x4 matrix in column-major order + */ + public Matrix4f(final FloatBuffer m) { + load(m); + } + // - // Write to Matrix via load(..) + // Write to Matrix via set(..) or load(..) // + /** Sets the {@code i}th component with float {@code v} 0 <= i < 16 */ + public void set(final int i, final float v) { + switch (i) { + case 0+4*0: m00 = v; break; + case 1+4*0: m10 = v; break; + case 2+4*0: m20 = v; break; + case 3+4*0: m30 = v; break; + + case 0+4*1: m01 = v; break; + case 1+4*1: m11 = v; break; + case 2+4*1: m21 = v; break; + case 3+4*1: m31 = v; break; + + case 0+4*2: m02 = v; break; + case 1+4*2: m12 = v; break; + case 2+4*2: m22 = v; break; + case 3+4*2: m32 = v; break; + + case 0+4*3: m03 = v; break; + case 1+4*3: m13 = v; break; + case 2+4*3: m23 = v; break; + case 3+4*3: m33 = v; break; + default: throw new IndexOutOfBoundsException(); + } + } + /** * Set this matrix to identity. * <pre> @@ -242,7 +276,7 @@ public class Matrix4f { // Read out Matrix via get(..) // - /** Gets the ith component, 0 <= i < 16 */ + /** Gets the {@code i}th component, 0 <= i < 16 */ public float get(final int i) { switch (i) { case 0+4*0: return m00; @@ -686,10 +720,6 @@ public class Matrix4f { /** * Multiply matrix: [this] = [this] x [b] - * <p> - * Roughly 15% slower than {@link #mul(Matrix4f, Matrix4f)} - * Roughly 3% slower than {@link FloatUtil#multMatrix(float[], float[])} - * </p> * @param b 4x4 matrix * @return this matrix for chaining * @see #mul(Matrix4f, Matrix4f) @@ -736,10 +766,6 @@ public class Matrix4f { /** * Multiply matrix: [this] = [a] x [b] - * <p> - * Roughly 13% faster than {@link #mul(Matrix4f)} - * Roughly 11% faster than {@link FloatUtil#multMatrix(float[], float[])} - * </p> * @param a 4x4 matrix, can't be this matrix * @param b 4x4 matrix, can't be this matrix * @return this matrix for chaining @@ -778,21 +804,6 @@ public class Matrix4f { * @param v_out this * v_in * @returns v_out for chaining */ - public final float[] mulVec4f(final float[/*4*/] v_in, final float[/*4*/] v_out) { - // (one matrix row in column-major order) X (column vector) - final float x = v_in[0], y = v_in[1], z = v_in[2], w = v_in[3]; - v_out[0] = x * m00 + y * m01 + z * m02 + w * m03; - v_out[1] = x * m10 + y * m11 + z * m12 + w * m13; - v_out[2] = x * m20 + y * m21 + z * m22 + w * m23; - v_out[3] = x * m30 + y * m31 + z * m32 + w * m33; - return v_out; - } - - /** - * @param v_in 4-component column-vector - * @param v_out this * v_in - * @returns v_out for chaining - */ public final Vec4f mulVec4f(final Vec4f v_in, final Vec4f v_out) { // (one matrix row in column-major order) X (column vector) final float x = v_in.x(), y = v_in.y(), z = v_in.z(), w = v_in.w(); @@ -807,26 +818,6 @@ public class Matrix4f { * Affine 3f-vector transformation by 4x4 matrix * * 4x4 matrix multiplication with 3-component vector, - * using {@code 1} for for {@code v_in[3]} and dropping {@code v_out[3]}, - * which shall be {@code 1}. - * - * @param v_in 3-component column-vector - * @param v_out m_in * v_in, 3-component column-vector - * @returns v_out for chaining - */ - public final float[] mulVec3f(final float[/*3*/] v_in, final float[/*3*/] v_out) { - // (one matrix row in column-major order) X (column vector) - final float x = v_in[0], y = v_in[1], z = v_in[2]; - v_out[0] = x * m00 + y * m01 + z * m02 + 1f * m03; - v_out[1] = x * m10 + y * m11 + z * m12 + 1f * m13; - v_out[2] = x * m20 + y * m21 + z * m22 + 1f * m23; - return v_out; - } - - /** - * Affine 3f-vector transformation by 4x4 matrix - * - * 4x4 matrix multiplication with 3-component vector, * using {@code 1} for for {@code v_in.w()} and dropping {@code v_out.w()}, * which shall be {@code 1}. * @@ -916,6 +907,22 @@ public class Matrix4f { } /** + * Set this matrix to scale. + * <pre> + Scale matrix (Any Order): + x 0 0 0 + 0 y 0 0 + 0 0 z 0 + 0 0 0 1 + * </pre> + * @param s scale Vec3f + * @return this matrix for chaining + */ + public final Matrix4f setToScale(final Vec3f s) { + return setToScale(s.x(), s.y(), s.z()); + } + + /** * Set this matrix to rotation from the given axis and angle in radians. * <pre> Rotation matrix (Column Order): @@ -936,9 +943,8 @@ public class Matrix4f { final float ic= 1.0f - c; final float s = FloatUtil.sin(ang_rad); - final float[] tmpVec3f = { x, y, z }; - VectorUtil.normalizeVec3(tmpVec3f); - x = tmpVec3f[0]; y = tmpVec3f[1]; z = tmpVec3f[2]; + final Vec3f tmp = new Vec3f(x, y, z).normalize(); + x = tmp.x(); y = tmp.y(); z = tmp.z(); final float xy = x*y; final float xz = x*z; @@ -1043,6 +1049,31 @@ public class Matrix4f { } /** + * Set this matrix to rotation from the given Euler rotation angles in radians. + * <p> + * The rotations are applied in the given order: + * <ul> + * <li>y - heading</li> + * <li>z - attitude</li> + * <li>x - bank</li> + * </ul> + * </p> + * @param angradXYZ euler angle vector in radians holding x-bank, y-heading and z-attitude + * @return this quaternion for chaining. + * <p> + * Implementation does not use Quaternion and hence is exposed to + * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a>, + * consider using {@link #setToRotation(Quaternion)}. + * </p> + * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q36">Matrix-FAQ Q36</a> + * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm">euclideanspace.com-eulerToMatrix</a> + * @see #setToRotation(Quaternion) + */ + public Matrix4f setToRotationEuler(final Vec3f angradXYZ) { + return setToRotationEuler(angradXYZ.x(), angradXYZ.y(), angradXYZ.z()); + } + + /** * Set this matrix to rotation using the given Quaternion. * <p> * Implementation Details: @@ -1055,7 +1086,7 @@ public class Matrix4f { * @param q the Quaternion representing the rotation * @return this matrix for chaining * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54">Matrix-FAQ Q54</a> - * @see Quaternion#toMatrix(float[], int) + * @see Quaternion#toMatrix(float[]) * @see #getRotation() */ public final Matrix4f setToRotation(final Quaternion q) { @@ -1255,7 +1286,7 @@ public class Matrix4f { * @return this matrix for chaining * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear} * @see #setToFrustum(float, float, float, float, float, float) - * @see Frustum#updateByFovDesc(float[], int, boolean, Frustum.FovDesc) + * @see Frustum#updateByFovDesc(Matrix4f, com.jogamp.opengl.math.geom.Frustum.FovDesc) */ public Matrix4f setToPerspective(final FovHVHalves fovhv, final float zNear, final float zFar) throws IllegalArgumentException { final FovHVHalves fovhvTan = fovhv.toTangents(); // use tangent of half-fov ! @@ -1268,11 +1299,14 @@ public class Matrix4f { /** * Calculate the frustum planes in world coordinates - * using the passed float[16] as premultiplied P*MV (column major order). + * using this premultiplied P*MV (column major order) matrix. * <p> * Frustum plane's normals will point to the inside of the viewing frustum, * as required by this class. * </p> + * <p> + * Usually called by {@link Frustum#updateFrustumPlanes(Matrix4f)}. + * </p> */ public void updateFrustumPlanes(final Frustum frustum) { // Left: a = m41 + m11, b = m42 + m12, c = m43 + m13, d = m44 + m14 - [1..4] column-major @@ -1352,7 +1386,7 @@ public class Matrix4f { } /** - * Make given matrix the <i>look-at</i> matrix based on given parameters. + * Set this matrix to the <i>look-at</i> matrix based on given parameters. * <p> * Consist out of two matrix multiplications: * <pre> @@ -1406,6 +1440,50 @@ public class Matrix4f { return mul( tmp.setToTranslation( -eye.x(), -eye.y(), -eye.z() ) ); } + /** + * Set this matrix to the <i>pick</i> matrix based on given parameters. + * <p> + * Traditional <code>gluPickMatrix</code> implementation. + * </p> + * <p> + * Consist out of two matrix multiplications: + * <pre> + * <b>R</b> = <b>T</b> x <b>S</b>, + * with <b>T</b> for viewport translation matrix and + * <b>S</b> for viewport scale matrix. + * + * Result <b>R</b> can be utilized for <i>projection</i> multiplication, i.e. + * <b>P</b> = <b>P</b> x <b>R</b>, + * with <b>P</b> being the <i>projection</i> matrix. + * </pre> + * </p> + * <p> + * To effectively use the generated pick matrix for picking, + * call {@link #setToPick(float, float, float, float, Recti, Matrix4f) setToPick(..)} + * and multiply a {@link #setToPerspective(float, float, float, float) custom perspective matrix} + * by this pick matrix. Then you may load the result onto the perspective matrix stack. + * </p> + * @param x the center x-component of a picking region in window coordinates + * @param y the center y-component of a picking region in window coordinates + * @param deltaX the width of the picking region in window coordinates. + * @param deltaY the height of the picking region in window coordinates. + * @param viewport Rect4i viewport + * @param mat4Tmp temp storage + * @return this matrix for chaining or {@code null} if either delta value is <= zero. + */ + public Matrix4f setToPick(final float x, final float y, final float deltaX, final float deltaY, + final Recti viewport, final Matrix4f mat4Tmp) { + if (deltaX <= 0 || deltaY <= 0) { + return null; + } + /* Translate and scale the picked region to the entire window */ + setToTranslation( ( viewport.width() - 2 * ( x - viewport.x() ) ) / deltaX, + ( viewport.height() - 2 * ( y - viewport.y() ) ) / deltaY, + 0); + mat4Tmp.setToScale( viewport.width() / deltaX, viewport.height() / deltaY, 1.0f ); + return mul(mat4Tmp); + } + // // Matrix affine operations using setTo..() // @@ -1587,12 +1665,12 @@ public class Matrix4f { * @param obj object position, 3 component vector * @param mMv modelview matrix * @param mP projection matrix - * @param viewport 4 component viewport vector + * @param viewport Rect4i viewport * @param winPos 3 component window coordinate, the result * @return true if successful, otherwise false (z is 1) */ public static boolean mapObjToWin(final Vec3f obj, final Matrix4f mMv, final Matrix4f mP, - final int[] viewport, final float[] winPos) + final Recti viewport, final Vec3f winPos) { final Vec4f vec4Tmp1 = new Vec4f(obj, 1f); @@ -1613,9 +1691,9 @@ public class Matrix4f { rawWinPos.scale(s).add(0.5f, 0.5f, 0.5f, 0f); // Map x,y to viewport - winPos[0] = rawWinPos.x() * viewport[2] + viewport[0]; - winPos[1] = rawWinPos.y() * viewport[3] + viewport[1]; - winPos[2] = rawWinPos.z(); + winPos.set( rawWinPos.x() * viewport.width() + viewport.x(), + rawWinPos.y() * viewport.height() + viewport.y(), + rawWinPos.z() ); return true; } @@ -1628,12 +1706,12 @@ public class Matrix4f { * * @param obj object position, 3 component vector * @param mPMv [projection] x [modelview] matrix, i.e. P x Mv - * @param viewport 4 component viewport vector + * @param viewport Rect4i viewport * @param winPos 3 component window coordinate, the result * @return true if successful, otherwise false (z is 1) */ public static boolean mapObjToWin(final Vec3f obj, final Matrix4f mPMv, - final int[] viewport, final float[] winPos) + final Recti viewport, final Vec3f winPos) { final Vec4f vec4Tmp2 = new Vec4f(obj, 1f); @@ -1650,9 +1728,9 @@ public class Matrix4f { rawWinPos.scale(s).add(0.5f, 0.5f, 0.5f, 0f); // Map x,y to viewport - winPos[0] = rawWinPos.x() * viewport[2] + viewport[0]; - winPos[1] = rawWinPos.y() * viewport[3] + viewport[1]; - winPos[2] = rawWinPos.z(); + winPos.set( rawWinPos.x() * viewport.width() + viewport.x(), + rawWinPos.y() * viewport.height() + viewport.y(), + rawWinPos.z() ); return true; } @@ -1668,14 +1746,14 @@ public class Matrix4f { * @param winz * @param mMv 4x4 modelview matrix * @param mP 4x4 projection matrix - * @param viewport 4 component viewport vector + * @param viewport Rect4i viewport * @param objPos 3 component object coordinate, the result * @param mat4Tmp 16 component matrix for temp storage * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z) */ public static boolean mapWinToObj(final float winx, final float winy, final float winz, final Matrix4f mMv, final Matrix4f mP, - final int[] viewport, + final Recti viewport, final Vec3f objPos, final Matrix4f mat4Tmp) { @@ -1688,7 +1766,7 @@ public class Matrix4f { final Vec4f winPos = new Vec4f(winx, winy, winz, 1f); // Map x and y from window coordinates - winPos.add(-viewport[0], -viewport[1], 0f, 0f).scale(1f/viewport[2], 1f/viewport[3], 1f, 1f); + winPos.add(-viewport.x(), -viewport.y(), 0f, 0f).scale(1f/viewport.width(), 1f/viewport.height(), 1f, 1f); // Map to range -1 to 1 winPos.scale(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f); @@ -1714,21 +1792,21 @@ public class Matrix4f { * @param winy * @param winz * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv) - * @param viewport 4 component viewport vector + * @param viewport Rect4i viewport * @param objPos 3 component object coordinate, the result * @param mat4Tmp 16 component matrix for temp storage * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z) */ public static boolean mapWinToObj(final float winx, final float winy, final float winz, final Matrix4f invPMv, - final int[] viewport, + final Recti viewport, final Vec3f objPos, final Matrix4f mat4Tmp) { final Vec4f winPos = new Vec4f(winx, winy, winz, 1f); // Map x and y from window coordinates - winPos.add(-viewport[0], -viewport[1], 0f, 0f).scale(1f/viewport[2], 1f/viewport[3], 1f, 1f); + winPos.add(-viewport.x(), -viewport.y(), 0f, 0f).scale(1f/viewport.width(), 1f/viewport.height(), 1f, 1f); // Map to range -1 to 1 winPos.scale(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f); @@ -1756,21 +1834,21 @@ public class Matrix4f { * @param winz1 * @param winz2 * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv) - * @param viewport 4 component viewport vector + * @param viewport Rect4i viewport vector * @param objPos1 3 component object coordinate, the result * @param mat4Tmp 16 component matrix for temp storage * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z) */ public static boolean mapWinToObj(final float winx, final float winy, final float winz1, final float winz2, final Matrix4f invPMv, - final int[] viewport, + final Recti viewport, final Vec3f objPos1, final Vec3f objPos2, final Matrix4f mat4Tmp) { final Vec4f winPos = new Vec4f(winx, winy, winz1, 1f); // Map x and y from window coordinates - winPos.add(-viewport[0], -viewport[1], 0f, 0f).scale(1f/viewport[2], 1f/viewport[3], 1f, 1f); + winPos.add(-viewport.x(), -viewport.y(), 0f, 0f).scale(1f/viewport.width(), 1f/viewport.height(), 1f, 1f); // Map to range -1 to 1 winPos.scale(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f); @@ -1812,7 +1890,7 @@ public class Matrix4f { * @param clipw * @param mMv 4x4 modelview matrix * @param mP 4x4 projection matrix - * @param viewport 4 component viewport vector + * @param viewport Rect4i viewport vector * @param near * @param far * @param obj_pos 4 component object coordinate, the result @@ -1821,7 +1899,7 @@ public class Matrix4f { */ public static boolean mapWinToObj4(final float winx, final float winy, final float winz, final float clipw, final Matrix4f mMv, final Matrix4f mP, - final int[] viewport, + final Recti viewport, final float near, final float far, final Vec4f objPos, final Matrix4f mat4Tmp) @@ -1835,7 +1913,7 @@ public class Matrix4f { final Vec4f winPos = new Vec4f(winx, winy, winz, clipw); // Map x and y from window coordinates - winPos.add(-viewport[0], -viewport[1], -near, 0f).scale(1f/viewport[2], 1f/viewport[3], 1f/(far-near), 1f); + winPos.add(-viewport.x(), -viewport.y(), -near, 0f).scale(1f/viewport.width(), 1f/viewport.height(), 1f/(far-near), 1f); // Map to range -1 to 1 winPos.scale(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f); @@ -1852,7 +1930,7 @@ public class Matrix4f { /** * Map two window coordinates w/ shared X/Y and distinctive Z * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i> - * using a {@link AABBox#getRayIntersection(Ray, float[]) bounding box}. + * using a {@link AABBox#getRayIntersection(Vec3f, Ray, float, boolean)}. * <p> * Notes for picking <i>winz0</i> and <i>winz1</i>: * <ul> @@ -1867,7 +1945,7 @@ public class Matrix4f { * @param winz1 * @param mMv 4x4 modelview matrix * @param mP 4x4 projection matrix - * @param viewport 4 component viewport vector + * @param viewport Rect4i viewport * @param ray storage for the resulting {@link Ray} * @param mat4Tmp1 16 component matrix for temp storage * @param mat4Tmp2 16 component matrix for temp storage @@ -1876,7 +1954,7 @@ public class Matrix4f { public static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1, final Matrix4f mMv, final Matrix4f mP, - final int[] viewport, + final Recti viewport, final Ray ray, final Matrix4f mat4Tmp1, final Matrix4f mat4Tmp2) { // invPMv = Inv(P x Mv) diff --git a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java index 2bb0f96c6..a285774f8 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java +++ b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java @@ -1000,18 +1000,17 @@ public class Quaternion { * </p> * * @param matrix float[16] store for the resulting normalized column matrix 4x4 - * @param mat_offset * @return the given matrix store * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54">Matrix-FAQ Q54</a> * @see #setFromMatrix(Matrix4f) * @see #setFromMatrix(float, float, float, float, float, float, float, float, float) */ - public final float[] toMatrix(final float[] matrix, final int mat_offset) { + public final float[] toMatrix(final float[] matrix) { // pre-multiply scaled-reciprocal-magnitude to reduce multiplications final float norm = magnitudeSquared(); if ( FloatUtil.isZero(norm, FloatUtil.EPSILON) ) { // identity matrix -> srecip = 0f - return FloatUtil.makeIdentity(matrix, mat_offset); + return FloatUtil.makeIdentity(matrix); } final float srecip; if ( FloatUtil.isEqual(1f, norm, FloatUtil.EPSILON) ) { @@ -1034,25 +1033,25 @@ public class Quaternion { final float zz = z * zs; final float zw = zs * w; - matrix[0+0*4+mat_offset] = 1f - ( yy + zz ); - matrix[0+1*4+mat_offset] = ( xy - zw ); - matrix[0+2*4+mat_offset] = ( xz + yw ); - matrix[0+3*4+mat_offset] = 0f; - - matrix[1+0*4+mat_offset] = ( xy + zw ); - matrix[1+1*4+mat_offset] = 1f - ( xx + zz ); - matrix[1+2*4+mat_offset] = ( yz - xw ); - matrix[1+3*4+mat_offset] = 0f; - - matrix[2+0*4+mat_offset] = ( xz - yw ); - matrix[2+1*4+mat_offset] = ( yz + xw ); - matrix[2+2*4+mat_offset] = 1f - ( xx + yy ); - matrix[2+3*4+mat_offset] = 0f; - - matrix[3+0*4+mat_offset] = 0f; - matrix[3+1*4+mat_offset] = 0f; - matrix[3+2*4+mat_offset] = 0f; - matrix[3+3*4+mat_offset] = 1f; + matrix[0+0*4] = 1f - ( yy + zz ); + matrix[0+1*4] = ( xy - zw ); + matrix[0+2*4] = ( xz + yw ); + matrix[0+3*4] = 0f; + + matrix[1+0*4] = ( xy + zw ); + matrix[1+1*4] = 1f - ( xx + zz ); + matrix[1+2*4] = ( yz - xw ); + matrix[1+3*4] = 0f; + + matrix[2+0*4] = ( xz - yw ); + matrix[2+1*4] = ( yz + xw ); + matrix[2+2*4] = 1f - ( xx + yy ); + matrix[2+3*4] = 0f; + + matrix[3+0*4] = 0f; + matrix[3+1*4] = 0f; + matrix[3+2*4] = 0f; + matrix[3+3*4] = 1f; return matrix; } diff --git a/src/jogl/classes/com/jogamp/opengl/math/Recti.java b/src/jogl/classes/com/jogamp/opengl/math/Recti.java new file mode 100644 index 000000000..58f5e5e77 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/math/Recti.java @@ -0,0 +1,134 @@ +/** + * Copyright 2022-2023 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: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.math; + +/** + * Rectangle with x, y, width and height integer components. + */ +public final class Recti { + private int x; + private int y; + private int width; + private int height; + + public Recti() {} + + public Recti(final Recti o) { + set(o); + } + + public Recti copy() { + return new Recti(this); + } + + public Recti(final int[/*4*/] xywh) { + set(xywh); + } + + public Recti(final int x, final int y, final int width, final int height) { + set(x, y, width, height); + } + + /** this = o, returns this. */ + public void set(final Recti o) { + this.x = o.x; + this.y = o.y; + this.width = o.width; + this.height= o.height; + } + + /** this = { x, y, width, height }, returns this. */ + public void set(final int x, final int y, final int width, final int height) { + this.x = x; + this.y = y; + this.width = width; + this.height= height; + } + + /** this = xywh, returns this. */ + public Recti set(final int[/*2*/] xywh) { + this.x = xywh[0]; + this.y = xywh[1]; + this.width = xywh[2]; + this.height= xywh[3]; + return this; + } + + /** xywh = this, returns xy. */ + public int[] get(final int[/*4*/] xywh) { + xywh[0] = this.x; + xywh[1] = this.y; + xywh[2] = this.width; + xywh[3] = this.height; + return xywh; + } + + public int x() { return x; } + public int y() { return y; } + public int width() { return width; } + public int height() { return height; } + + public void setX(final int x) { this.x = x; } + public void setY(final int y) { this.y = y; } + public void setWidth(final int width) { this.width = width; } + public void setHeight(final int height) { this.height = height; } + + /** Return true if all components are zero. */ + public boolean isZero() { + return 0 == x && 0 == y; + } + + /** + * Equals check. + * @param o comparison value + * @return true if all components are equal + */ + public boolean isEqual(final Recti o) { + if( this == o ) { + return true; + } else { + return x == o.x && y == o.y && + width == o.width && height == o.height; + } + } + + @Override + public boolean equals(final Object o) { + if( o instanceof Recti ) { + return isEqual((Recti)o); + } else { + return false; + } + } + + @Override + public String toString() { + return x + " / " + y + " " + width + " x " + height; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vec2f.java b/src/jogl/classes/com/jogamp/opengl/math/Vec2f.java index 0c7854216..616ba0f60 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/Vec2f.java +++ b/src/jogl/classes/com/jogamp/opengl/math/Vec2f.java @@ -301,13 +301,6 @@ public final class Vec2f { return new Vec2f(-y, x); } - public boolean intersects(final Vec2f o) { - if( Math.abs(x-o.x) >= FloatUtil.EPSILON || Math.abs(y-o.y) >= FloatUtil.EPSILON ) { - return false; - } - return true; - } - /** * Equals check using a given {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}. * <p> diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vec2i.java b/src/jogl/classes/com/jogamp/opengl/math/Vec2i.java new file mode 100644 index 000000000..9e70a502f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/math/Vec2i.java @@ -0,0 +1,153 @@ +/** + * Copyright 2022-2023 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: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.math; + +/** + * 2D Vector based upon two integer components. + */ +public final class Vec2i { + private int x; + private int y; + + public Vec2i() {} + + public Vec2i(final Vec2i o) { + set(o); + } + + public Vec2i copy() { + return new Vec2i(this); + } + + public Vec2i(final int[/*2*/] xy) { + set(xy); + } + + public Vec2i(final int x, final int y) { + set(x, y); + } + + /** this = o, returns this. */ + public void set(final Vec2i o) { + this.x = o.x; + this.y = o.y; + } + + /** this = { x, y }, returns this. */ + public void set(final int x, final int y) { + this.x = x; + this.y = y; + } + + /** this = xy, returns this. */ + public Vec2i set(final int[/*2*/] xy) { + this.x = xy[0]; + this.y = xy[1]; + return this; + } + + /** xy = this, returns xy. */ + public int[] get(final int[/*2*/] xy) { + xy[0] = this.x; + xy[1] = this.y; + return xy; + } + + public int x() { return x; } + public int y() { return y; } + + public void setX(final int x) { this.x = x; } + public void setY(final int y) { this.y = y; } + + /** Return true if all components are zero. */ + public boolean isZero() { + return 0 == x && 0 == y; + } + + /** + * Return the length of this vector, a.k.a the <i>norm</i> or <i>magnitude</i> + */ + public int length() { + return (int) Math.sqrt(lengthSq()); + } + + /** + * Return the squared length of this vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i> + */ + public int lengthSq() { + return x*x + y*y; + } + + /** + * Return the squared distance between this vector and the given one. + * <p> + * When comparing the relative distance between two points it is usually sufficient to compare the squared + * distances, thus avoiding an expensive square root operation. + * </p> + */ + public int distSq(final Vec2i o) { + final int dx = x - o.x; + final int dy = y - o.y; + return dx*dx + dy*dy; + } + + /** + * Return the distance between this vector and the given one. + */ + public int dist(final Vec2i o) { + return (int)Math.sqrt(distSq(o)); + } + + /** + * Equals check. + * @param o comparison value + * @return true if all components are equal + */ + public boolean isEqual(final Vec2i o) { + if( this == o ) { + return true; + } else { + return x == o.x && y == o.y; + } + } + + @Override + public boolean equals(final Object o) { + if( o instanceof Vec2i ) { + return isEqual((Vec2i)o); + } else { + return false; + } + } + + @Override + public String toString() { + return x + " / " + y; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vec3f.java b/src/jogl/classes/com/jogamp/opengl/math/Vec3f.java index d5c725ad7..9ef985b36 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/Vec3f.java +++ b/src/jogl/classes/com/jogamp/opengl/math/Vec3f.java @@ -312,14 +312,6 @@ public final class Vec3f { return (float) Math.acos( cosAngle(o) ); } - public boolean intersects(final Vec3f o) { - if( Math.abs(x-o.x) >= FloatUtil.EPSILON || Math.abs(y-o.y) >= FloatUtil.EPSILON || Math.abs(z-o.z) >= FloatUtil.EPSILON ) { - return false; - } else { - return true; - } - } - /** * Equals check using a given {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}. * <p> diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vec4f.java b/src/jogl/classes/com/jogamp/opengl/math/Vec4f.java index 1a20015a9..570b7b2b3 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/Vec4f.java +++ b/src/jogl/classes/com/jogamp/opengl/math/Vec4f.java @@ -284,14 +284,6 @@ public final class Vec4f { return (float) Math.acos( cosAngle(o) ); } - public boolean intersects(final Vec4f o) { - if( Math.abs(x-o.x) >= FloatUtil.EPSILON || Math.abs(y-o.y) >= FloatUtil.EPSILON || Math.abs(z-o.z) >= FloatUtil.EPSILON || - Math.abs(w-o.w) >= FloatUtil.EPSILON) { - return false; - } - return true; - } - /** * Equals check using a given {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}. * <p> diff --git a/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java b/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java index 77e1bfc59..ad521de2a 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java +++ b/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java @@ -32,6 +32,7 @@ import com.jogamp.opengl.math.FloatUtil; import com.jogamp.opengl.math.Matrix4f; import com.jogamp.opengl.math.Quaternion; import com.jogamp.opengl.math.Ray; +import com.jogamp.opengl.math.Recti; import com.jogamp.opengl.math.Vec3f; import com.jogamp.opengl.util.PMVMatrix; @@ -718,41 +719,34 @@ public class AABBox { throw new InternalError("hashCode not designed"); } - public AABBox transform(final AABBox result, final float[/*16*/] mat4, final int mat4_off, - final float[] vec3Tmp0, final float[] vec3Tmp1) { - result.reset(); - FloatUtil.multMatrixVec3(mat4, mat4_off, low.get(vec3Tmp0), vec3Tmp1); - result.resize(vec3Tmp1); - - FloatUtil.multMatrixVec3(mat4, mat4_off, high.get(vec3Tmp0), vec3Tmp1); - result.resize(vec3Tmp1); - - result.computeCenter(); - return result; - } - - public AABBox transformMv(final AABBox result, final PMVMatrix pmv, - final float[] vec3Tmp0, final float[] vec3Tmp1) { - result.reset(); - pmv.multMvMatVec3f(low.get(vec3Tmp0), vec3Tmp1); - result.resize(vec3Tmp1); - - pmv.multMvMatVec3f(high.get(vec3Tmp0), vec3Tmp1); - result.resize(vec3Tmp1); - - result.computeCenter(); - return result; + /** + * Transform this box using the given {@link Matrix4f} into {@code out} + * @param mat transformation {@link Matrix4f} + * @param out the resulting {@link AABBox} + * @return the resulting {@link AABBox} for chaining + */ + public AABBox transform(final Matrix4f mat, final AABBox out) { + final Vec3f tmp = new Vec3f(); + out.reset(); + out.resize( mat.mulVec3f(low, tmp) ); + out.resize( mat.mulVec3f(high, tmp) ); + out.computeCenter(); + return out; } - public AABBox transform(final AABBox result, final Matrix4f mat, - final Vec3f vec3Tmp) { - result.reset(); - result.resize( mat.mulVec3f(low, vec3Tmp) ); - - result.resize( mat.mulVec3f(high, vec3Tmp) ); - - result.computeCenter(); - return result; + /** + * Transform this box using the {@link PMVMatrix#getMvMat() modelview} of the given {@link PMVMatrix} into {@code out} + * @param pmv transformation {@link PMVMatrix} + * @param out the resulting {@link AABBox} + * @return the resulting {@link AABBox} for chaining + */ + public AABBox transformMv(final PMVMatrix pmv, final AABBox out) { + final Vec3f tmp = new Vec3f(); + out.reset(); + out.resize( pmv.mulMvMatVec3f(low, tmp) ); + out.resize( pmv.mulMvMatVec3f(high, tmp) ); + out.computeCenter(); + return out; } /** @@ -771,56 +765,51 @@ public class AABBox { * | | * .y() ------ [3] * </pre> - * @param mat4PMv P x Mv matrix - * @param view + * @param mat4PMv [projection] x [modelview] matrix, i.e. P x Mv + * @param viewport viewport rectangle * @param useCenterZ * @param vec3Tmp0 3 component vector for temp storage * @param vec4Tmp1 4 component vector for temp storage * @param vec4Tmp2 4 component vector for temp storage * @return */ - public AABBox mapToWindow(final AABBox result, final float[/*16*/] mat4PMv, final int[] view, final boolean useCenterZ, - final float[] vec3Tmp0, final float[] vec4Tmp1, final float[] vec4Tmp2) { + public AABBox mapToWindow(final AABBox result, final Matrix4f mat4PMv, final Recti viewport, final boolean useCenterZ) { + final Vec3f tmp = new Vec3f(); + final Vec3f winPos = new Vec3f(); { - // System.err.printf("AABBox.mapToWindow.0: view[%d, %d, %d, %d], this %s%n", view.x(), view.y(), view.z(), view[3], toString()); final float objZ = useCenterZ ? center.z() : getMinZ(); - FloatUtil.mapObjToWin(getMinX(), getMinY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); - // System.err.printf("AABBox.mapToWindow.p1: %f, %f, %f -> %f, %f, %f%n", getMinX(), getMinY(), objZ, vec3Tmp0.x(), vec3Tmp0.y(), vec3Tmp0.z()); - // System.err.println("AABBox.mapToWindow.p1:"); - // System.err.println(FloatUtil.matrixToString(null, " mat4PMv", "%10.5f", mat4PMv, 0, 4, 4, false /* rowMajorOrder */)); - result.reset(); - result.resize(vec3Tmp0); - FloatUtil.mapObjToWin(getMinX(), getMaxY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); - // System.err.printf("AABBox.mapToWindow.p2: %f, %f, %f -> %f, %f, %f%n", getMinX(), getMaxY(), objZ, vec3Tmp0.x(), vec3Tmp0.y(), vec3Tmp0.z()); - result.resize(vec3Tmp0); + Matrix4f.mapObjToWin(tmp.set(getMinX(), getMinY(), objZ), mat4PMv, viewport, winPos); + result.resize(winPos); - FloatUtil.mapObjToWin(getMaxX(), getMinY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); - // System.err.printf("AABBox.mapToWindow.p3: %f, %f, %f -> %f, %f, %f%n", getMaxX(), getMinY(), objZ, vec3Tmp0.x(), vec3Tmp0.y(), vec3Tmp0.z()); - result.resize(vec3Tmp0); + Matrix4f.mapObjToWin(tmp.set(getMinX(), getMaxY(), objZ), mat4PMv, viewport, winPos); + result.resize(winPos); - FloatUtil.mapObjToWin(getMaxX(), getMaxY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); - // System.err.printf("AABBox.mapToWindow.p4: %f, %f, %f -> %f, %f, %f%n", getMaxX(), getMaxY(), objZ, vec3Tmp0.x(), vec3Tmp0.y(), vec3Tmp0.z()); - result.resize(vec3Tmp0); + Matrix4f.mapObjToWin(tmp.set(getMaxX(), getMaxY(), objZ), mat4PMv, viewport, winPos); + result.resize(winPos); + + Matrix4f.mapObjToWin(tmp.set(getMaxX(), getMinY(), objZ), mat4PMv, viewport, winPos); + result.resize(winPos); } if( !useCenterZ ) { final float objZ = getMaxZ(); - FloatUtil.mapObjToWin(getMinX(), getMinY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); - result.resize(vec3Tmp0); - FloatUtil.mapObjToWin(getMinX(), getMaxY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); - result.resize(vec3Tmp0); + Matrix4f.mapObjToWin(tmp.set(getMinX(), getMinY(), objZ), mat4PMv, viewport, winPos); + result.resize(winPos); + + Matrix4f.mapObjToWin(tmp.set(getMinX(), getMaxY(), objZ), mat4PMv, viewport, winPos); + result.resize(winPos); - FloatUtil.mapObjToWin(getMaxX(), getMinY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); - result.resize(vec3Tmp0); + Matrix4f.mapObjToWin(tmp.set(getMaxX(), getMaxY(), objZ), mat4PMv, viewport, winPos); + result.resize(winPos); - FloatUtil.mapObjToWin(getMaxX(), getMaxY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); - result.resize(vec3Tmp0); + Matrix4f.mapObjToWin(tmp.set(getMaxX(), getMinY(), objZ), mat4PMv, viewport, winPos); + result.resize(winPos); } if( DEBUG ) { - System.err.printf("AABBox.mapToWindow: view[%d, %d], this %s -> %s%n", view[0], view[1], toString(), result.toString()); + System.err.printf("AABBox.mapToWindow: view[%s], this %s -> %s%n", viewport, toString(), result.toString()); } return result; } diff --git a/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java b/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java index 4d098cb72..f72154827 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java +++ b/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java @@ -37,7 +37,7 @@ import com.jogamp.opengl.math.geom.Frustum.FovDesc; /** * Providing frustum {@link #getPlanes() planes} derived by different inputs - * ({@link #updateByPMV(float[], int) P*MV}, ..) used to classify objects + * ({@link #updateFrustumPlanes(float[], int) P*MV}, ..) used to classify objects * <ul> * <li> {@link #classifyPoint(float[]) point} </li> * <li> {@link #classifySphere(float[], float) sphere} </li> @@ -120,7 +120,7 @@ public class Frustum { * Use one of the <code>update(..)</code> methods to set the {@link #getPlanes() planes}. * </p> * @see #updateByPlanes(Plane[]) - * @see #updateByPMV(float[], int) + * @see #updateFrustumPlanes(float[], int) */ public Frustum() { for (int i = 0; i < 6; ++i) { @@ -162,11 +162,6 @@ public class Frustum { } /** Return distance of plane to given point, see {@link #distanceTo(float, float, float)}. */ - public final float distanceTo(final float[] p) { - return n.x() * p[0] + n.y() * p[1] + n.z() * p[2] + d; - } - - /** Return distance of plane to given point, see {@link #distanceTo(float, float, float)}. */ public final float distanceTo(final Vec3f p) { return n.x() * p.x() + n.y() * p.y() + n.z() * p.z() + d; } @@ -254,87 +249,14 @@ public class Frustum { /** * Calculate the frustum planes in world coordinates - * using the passed float[16] as premultiplied P*MV (column major order). + * using the passed premultiplied P*MV (column major order) matrix. * <p> * Frustum plane's normals will point to the inside of the viewing frustum, * as required by this class. * </p> */ - public void updateByPMV(final float[] pmv, final int pmv_off) { - // Left: a = m41 + m11, b = m42 + m12, c = m43 + m13, d = m44 + m14 - [1..4] column-major - // Left: a = m30 + m00, b = m31 + m01, c = m32 + m02, d = m33 + m03 - [0..3] column-major - { - final Plane p = planes[LEFT]; - final Vec3f p_n = p.n; - p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 0 + 0 * 4 ], - pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 0 + 1 * 4 ], - pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 0 + 2 * 4 ] ); - p.d = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 0 + 3 * 4 ]; - } - - // Right: a = m41 - m11, b = m42 - m12, c = m43 - m13, d = m44 - m14 - [1..4] column-major - // Right: a = m30 - m00, b = m31 - m01, c = m32 - m02, d = m33 - m03 - [0..3] column-major - { - final Plane p = planes[RIGHT]; - final Vec3f p_n = p.n; - p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 0 + 0 * 4 ], - pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 0 + 1 * 4 ], - pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 0 + 2 * 4 ] ); - p.d = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 0 + 3 * 4 ]; - } - - // Bottom: a = m41 + m21, b = m42 + m22, c = m43 + m23, d = m44 + m24 - [1..4] column-major - // Bottom: a = m30 + m10, b = m31 + m11, c = m32 + m12, d = m33 + m13 - [0..3] column-major - { - final Plane p = planes[BOTTOM]; - final Vec3f p_n = p.n; - p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 1 + 0 * 4 ], - pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 1 + 1 * 4 ], - pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 1 + 2 * 4 ] ); - p.d = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 1 + 3 * 4 ]; - } - - // Top: a = m41 - m21, b = m42 - m22, c = m43 - m23, d = m44 - m24 - [1..4] column-major - // Top: a = m30 - m10, b = m31 - m11, c = m32 - m12, d = m33 - m13 - [0..3] column-major - { - final Plane p = planes[TOP]; - final Vec3f p_n = p.n; - p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 1 + 0 * 4 ], - pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 1 + 1 * 4 ], - pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 1 + 2 * 4 ] ); - p.d = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 1 + 3 * 4 ]; - } - - // Near: a = m41 + m31, b = m42 + m32, c = m43 + m33, d = m44 + m34 - [1..4] column-major - // Near: a = m30 + m20, b = m31 + m21, c = m32 + m22, d = m33 + m23 - [0..3] column-major - { - final Plane p = planes[NEAR]; - final Vec3f p_n = p.n; - p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 2 + 0 * 4 ], - pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 2 + 1 * 4 ], - pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 2 + 2 * 4 ] ); - p.d = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 2 + 3 * 4 ]; - } - - // Far: a = m41 - m31, b = m42 - m32, c = m43 - m33, d = m44 - m34 - [1..4] column-major - // Far: a = m30 - m20, b = m31 - m21, c = m32 + m22, d = m33 + m23 - [0..3] column-major - { - final Plane p = planes[FAR]; - final Vec3f p_n = p.n; - p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 2 + 0 * 4 ], - pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 2 + 1 * 4 ], - pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 2 + 2 * 4 ] ); - p.d = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 2 + 3 * 4 ]; - } - - // Normalize all planes - for (int i = 0; i < 6; ++i) { - final Plane p = planes[i]; - final Vec3f p_n = p.n; - final float invLen = 1f / p_n.length(); - p_n.scale(invLen); - p.d *= invLen; - } + public void updateFrustumPlanes(final Matrix4f pmv) { + pmv.updateFrustumPlanes(this); } private static final boolean isOutsideImpl(final Plane p, final AABBox box) { @@ -380,7 +302,7 @@ public class Frustum { * @param p the point * @return {@link Location} of point related to frustum planes */ - public final Location classifyPoint(final float[] p) { + public final Location classifyPoint(final Vec3f p) { Location res = Location.INSIDE; for (int i = 0; i < 6; ++i) { @@ -400,7 +322,7 @@ public class Frustum { * @param p the point * @return true if outside of the frustum, otherwise inside or on a plane */ - public final boolean isPointOutside(final float[] p) { + public final boolean isPointOutside(final Vec3f p) { return Location.OUTSIDE == classifyPoint(p); } @@ -411,7 +333,7 @@ public class Frustum { * @param radius radius of the sphere * @return {@link Location} of point related to frustum planes */ - public final Location classifySphere(final float[] p, final float radius) { + public final Location classifySphere(final Vec3f p, final float radius) { Location res = Location.INSIDE; // fully inside for (int i = 0; i < 6; ++i) { @@ -434,7 +356,7 @@ public class Frustum { * @param radius radius of the sphere * @return true if outside of the frustum, otherwise inside or intersecting */ - public final boolean isSphereOutside(final float[] p, final float radius) { + public final boolean isSphereOutside(final Vec3f p, final float radius) { return Location.OUTSIDE == classifySphere(p, radius); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java index 1aa305c2e..0d9617fb4 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java +++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java @@ -1,65 +1,68 @@ -/* - * 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: +/** + * Copyright 2009-2023 JogAmp Community. All rights reserved. * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: * - * - 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. + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. * - * 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. + * 2. Redistributions 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. * - * 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 - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * 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. + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. */ - package com.jogamp.opengl.util; +import java.nio.Buffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import com.jogamp.opengl.GL; import com.jogamp.opengl.GLException; import com.jogamp.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.opengl.GLUniformData; import jogamp.common.os.PlatformPropsImpl; import com.jogamp.common.nio.Buffers; -import com.jogamp.common.util.FloatStack; import com.jogamp.opengl.math.FloatUtil; import com.jogamp.opengl.math.Matrix4f; import com.jogamp.opengl.math.Quaternion; import com.jogamp.opengl.math.Ray; +import com.jogamp.opengl.math.Recti; +import com.jogamp.opengl.math.Vec3f; +import com.jogamp.opengl.math.Vec4f; import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.math.geom.Frustum; /** * PMVMatrix implements a subset of the fixed function pipeline - * regarding the projection (P), modelview (Mv) matrix operation + * regarding the projection (P), modelview (Mv) and texture (T) matrix operations, * 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()}. + * This is the second implementation of {@code PMVMatrix} using + * direct {@link Matrix4f}, {@link Vec4f} and {@link Vec3f} math operations instead of {@code float[]} + * via {@link com.jogamp.opengl.math.FloatUtil FloatUtil}. + * </p> + * <p> + * PMVMatrix provides the {@link #getMviMat() inverse modelview matrix (Mvi)} and + * {@link #getMvitMat() inverse transposed modelview matrix (Mvit)}. + * {@link Frustum} is also provided by {@link #getFrustum()}. + * * 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. @@ -67,7 +70,7 @@ import com.jogamp.opengl.math.geom.Frustum; * <p> * All matrices are provided in column-major order, * as specified in the OpenGL fixed function pipeline, i.e. compatibility profile. - * See {@link FloatUtil}. + * See {@link Matrix4f}. * </p> * <p> * PMVMatrix can supplement {@link GL2ES2} applications w/ the @@ -75,6 +78,23 @@ import com.jogamp.opengl.math.geom.Frustum; * </p> * <a name="storageDetails"><h5>Matrix storage details</h5></a> * <p> + * The {@link SyncBuffer} abstraction is provided, e.g. {@link #getSyncPMvMviMat()}, + * to synchronize the respective {@link Matrix4f matrices} with the {@code float[]} backing store. + * The latter is represents the data to {@link GLUniformData} via its {@link FloatBuffer}s, see {@link SyncBuffer#getBuffer()}, + * and is pushed to the GPU eventually. + * + * {@link SyncBuffer}'s {@link SyncAction} is called by {@link GLUniformData#getBuffer()}, + * i.e. before the data is pushed to the GPU. + * + * The provided {@link SyncAction} ensures that the {@link Matrix4f matrices data} + * gets copied into the {@code float[]} backing store. + * + * PMVMatrix provides two specializations of {@link SyncBuffer}, {@link SyncMatrix} for single {@link Matrix4f} mappings + * and {@link SyncMatrices4f} for multiple {@link Matrix4f} mappings. + * + * They can be feed directly to instantiate a {@link GLUniformData} object via e.g. {@link GLUniformData#GLUniformData(String, int, int, SyncBuffer)}. + * </p> + * <p> * All matrices are backed up by a common primitive float-array for performance considerations * and are a {@link Buffers#slice2Float(float[], int, int) sliced} representation of it. * </p> @@ -89,20 +109,20 @@ import com.jogamp.opengl.math.geom.Frustum; */ public final class PMVMatrix implements GLMatrixFunc { - /** Bit value stating a modified {@link #glGetPMatrixf() projection matrix (P)}, since last {@link #update()} call. */ + /** Bit value stating a modified {@link #getPMat() 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. */ + /** Bit value stating a modified {@link #getMvMat() 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. */ + /** Bit value stating a modified {@link #getTMat() 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)}. */ + /** Bit value stating a dirty {@link #getMviMat() inverse modelview matrix (Mvi)}. */ public static final int DIRTY_INVERSE_MODELVIEW = 1 << 0; - /** Bit value stating a dirty {@link #glGetMvitMatrixf() inverse transposed modelview matrix (Mvit)}. */ + /** Bit value stating a dirty {@link #getMvitMat() inverse transposed modelview matrix (Mvit)}. */ public static final int DIRTY_INVERSE_TRANSPOSED_MODELVIEW = 1 << 1; - /** Bit value stating a dirty {@link #glGetFrustum() frustum}. */ + /** Bit value stating a dirty {@link #getFrustum() frustum}. */ public static final int DIRTY_FRUSTUM = 1 << 2; /** Bit value stating all is dirty */ public static final int DIRTY_ALL = DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM; @@ -171,29 +191,6 @@ public final class PMVMatrix implements GLMatrixFunc { } /** - * @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 - */ - @SuppressWarnings("deprecation") - public static StringBuilder matrixToString(final StringBuilder sb, final String f, final 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 - */ - @SuppressWarnings("deprecation") - public static StringBuilder matrixToString(final StringBuilder sb, final String f, final FloatBuffer a, final FloatBuffer b) { - return FloatUtil.matrixToString(sb, null, f, a, 0, b, 0, 4, 4, false); - } - - /** * Creates an instance of PMVMatrix. * <p> * Implementation uses non-direct non-NIO Buffers with guaranteed backing array, @@ -207,31 +204,43 @@ public final class PMVMatrix implements GLMatrixFunc { // Mv ModelView // Mvi Modelview-Inverse // Mvit Modelview-Inverse-Transpose - matrixArray = new float[5*16]; - - // mP_offset = 0*16; - // mMv_offset = 1*16; - // mTex_offset = 4*16; - - matrixPMvMvit = Buffers.slice2Float(matrixArray, 0*16, 4*16); // P + Mv + Mvi + Mvit - matrixPMvMvi = Buffers.slice2Float(matrixArray, 0*16, 3*16); // P + Mv + Mvi - matrixPMv = Buffers.slice2Float(matrixArray, 0*16, 2*16); // P + Mv - matrixP = Buffers.slice2Float(matrixArray, 0*16, 1*16); // P - matrixMv = Buffers.slice2Float(matrixArray, 1*16, 1*16); // Mv - matrixMvi = Buffers.slice2Float(matrixArray, 2*16, 1*16); // Mvi - matrixMvit = Buffers.slice2Float(matrixArray, 3*16, 1*16); // Mvit - matrixTex = Buffers.slice2Float(matrixArray, 4*16, 1*16); // T - - mat4Tmp1 = new float[16]; - mat4Tmp2 = new float[16]; - mat4Tmp3 = new float[16]; - matrixTxSx = new float[16]; - FloatUtil.makeIdentity(matrixTxSx); - - // 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) + + // actual underlying Matrix4f data + matP = new Matrix4f(); + matMv = new Matrix4f(); + matMvi = new Matrix4f(); + matMvit = new Matrix4f(); + matTex = new Matrix4f(); + + // float back buffer for GPU, Matrix4f -> matrixStore via SyncedBuffer + matrixStore = new float[5*16]; + + // FloatBuffer for single Matrix4f back-buffer + matrixP = Buffers.slice2Float(matrixStore, mP_offset, 1*16); // P + matrixMv = Buffers.slice2Float(matrixStore, mMv_offset, 1*16); // Mv + matrixMvi = Buffers.slice2Float(matrixStore, mMvi_offset, 1*16); // Mvi + matrixMvit = Buffers.slice2Float(matrixStore, mMvit_offset, 1*16); // Mvit + matrixTex = Buffers.slice2Float(matrixStore, mTex_offset, 1*16); // T + + // FloatBuffer for aggregated multiple Matrix4f back-buffer + matrixPMvMvit = Buffers.slice2Float(matrixStore, mP_offset, 4*16); // P + Mv + Mvi + Mvit + matrixPMvMvi = Buffers.slice2Float(matrixStore, mP_offset, 3*16); // P + Mv + Mvi + matrixPMv = Buffers.slice2Float(matrixStore, mP_offset, 2*16); // P + Mv + + matPSync = new SyncBuffer0(matP, matrixP); // mP_offset + matMvSync = new SyncBuffer1(matMv, matrixMv, mMv_offset); + matMviSync = new SyncBuffer1(matMvi, matrixMvi, mMvi_offset); + matMvitSync = new SyncBuffer1(matMvit, matrixMvit, mMvit_offset); + matTexSync = new SyncBuffer1(matTex, matrixTex, mTex_offset); + + matPMvMvitSync = new SyncBufferN(new Matrix4f[] { matP, matMv, matMvi, matMvit }, matrixPMvMvit, mP_offset); + matPMvMviSync = new SyncBufferN(new Matrix4f[] { matP, matMv, matMvi }, matrixPMvMvi, mP_offset); + matPMvSync = new SyncBufferN(new Matrix4f[] { matP, matMv }, matrixPMv, mP_offset); + + mat4Tmp1 = new Matrix4f(); + mat4Tmp2 = new Matrix4f(); + vec3Tmp1 = new Vec3f(); + vec4Tmp1 = new Vec4f(); reset(); @@ -246,9 +255,9 @@ public final class PMVMatrix implements GLMatrixFunc { * Leaves {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW} the active matrix mode. */ public final void reset() { - FloatUtil.makeIdentity(matrixArray, mMv_offset); - FloatUtil.makeIdentity(matrixArray, mP_offset); - FloatUtil.makeIdentity(matrixArray, mTex_offset); + matP.loadIdentity(); + matMv.loadIdentity(); + matTex.loadIdentity(); modifiedBits = MODIFIED_ALL; dirtyBits = DIRTY_ALL; @@ -261,14 +270,27 @@ public final class PMVMatrix implements GLMatrixFunc { return matrixMode; } + // + // Matrix4f access as well as their SyncedBuffer counterpart SyncedMatrix and SyncedMatrices + // /** * 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; + public final Matrix4f getTMat() { + return matTex; + } + + /** + * Returns the {@link SyncMatrix} of {@link GLMatrixFunc#GL_TEXTURE_MATRIX texture matrix} (T). + * <p> + * See <a href="#storageDetails"> matrix storage details</a>. + * </p> + */ + public final SyncMatrix4f getSyncTMat() { + return matTexSync; } /** @@ -277,8 +299,18 @@ public final class PMVMatrix implements GLMatrixFunc { * See <a href="#storageDetails"> matrix storage details</a>. * </p> */ - public final FloatBuffer glGetPMatrixf() { - return matrixP; + public final Matrix4f getPMat() { + return matP; + } + + /** + * Returns the {@link SyncMatrix} of {@link GLMatrixFunc#GL_PROJECTION_MATRIX projection matrix} (P). + * <p> + * See <a href="#storageDetails"> matrix storage details</a>. + * </p> + */ + public final SyncMatrix4f getSyncPMat() { + return matPSync; } /** @@ -287,8 +319,18 @@ public final class PMVMatrix implements GLMatrixFunc { * See <a href="#storageDetails"> matrix storage details</a>. * </p> */ - public final FloatBuffer glGetMvMatrixf() { - return matrixMv; + public final Matrix4f getMvMat() { + return matMv; + } + + /** + * Returns the {@link SyncMatrix} of {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mv). + * <p> + * See <a href="#storageDetails"> matrix storage details</a>. + * </p> + */ + public final SyncMatrix4f getSyncMvMat() { + return matMvSync; } /** @@ -302,10 +344,27 @@ public final class PMVMatrix implements GLMatrixFunc { * @see #update() * @see #clearAllUpdateRequests() */ - public final FloatBuffer glGetMviMatrixf() { + public final Matrix4f getMviMat() { + requestMask |= DIRTY_INVERSE_MODELVIEW ; + updateImpl(false); + return matMvi; + } + + /** + * Returns the {@link SyncMatrix} of 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 SyncMatrix4f getSyncMviMat() { requestMask |= DIRTY_INVERSE_MODELVIEW ; updateImpl(false); - return matrixMvi; + return matMviSync; } /** @@ -319,24 +378,41 @@ public final class PMVMatrix implements GLMatrixFunc { * @see #update() * @see #clearAllUpdateRequests() */ - public final FloatBuffer glGetMvitMatrixf() { + public final Matrix4f getMvitMat() { requestMask |= DIRTY_INVERSE_TRANSPOSED_MODELVIEW ; updateImpl(false); - return matrixMvit; + return matMvit; } /** - * Returns 2 matrices within one FloatBuffer: {@link #glGetPMatrixf() P} and {@link #glGetMvMatrixf() Mv}. + * Returns the {@link SyncMatrix} of inverse transposed {@link GLMatrixFunc#GL_MODELVIEW_MATRIX modelview matrix} (Mvit). + * <p> + * Method enables the Mvit matrix update, and performs it's update w/o clearing the modified bits. + * </p> + * <p> + * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>. + * </p> + * @see #update() + * @see #clearAllUpdateRequests() + */ + public final SyncMatrix4f getSyncMvitMat() { + requestMask |= DIRTY_INVERSE_TRANSPOSED_MODELVIEW ; + updateImpl(false); + return matMvitSync; + } + + /** + * Returns {@link SyncMatrices4f} of 2 matrices within one FloatBuffer: {@link #getPMat() P} and {@link #getMvMat() Mv}. * <p> * See <a href="#storageDetails"> matrix storage details</a>. * </p> */ - public final FloatBuffer glGetPMvMatrixf() { - return matrixPMv; + public final SyncMatrices4f getSyncPMvMat() { + return matPMvSync; } /** - * Returns 3 matrices within one FloatBuffer: {@link #glGetPMatrixf() P}, {@link #glGetMvMatrixf() Mv} and {@link #glGetMviMatrixf() Mvi}. + * Returns {@link SyncMatrices4f} of 3 matrices within one FloatBuffer: {@link #getPMat() P}, {@link #getMvMat() Mv} and {@link #getMviMat() Mvi}. * <p> * Method enables the Mvi matrix update, and performs it's update w/o clearing the modified bits. * </p> @@ -346,14 +422,14 @@ public final class PMVMatrix implements GLMatrixFunc { * @see #update() * @see #clearAllUpdateRequests() */ - public final FloatBuffer glGetPMvMviMatrixf() { + public final SyncMatrices4f getSyncPMvMviMat() { requestMask |= DIRTY_INVERSE_MODELVIEW ; updateImpl(false); - return matrixPMvMvi; + return matPMvMviSync; } /** - * Returns 4 matrices within one FloatBuffer: {@link #glGetPMatrixf() P}, {@link #glGetMvMatrixf() Mv}, {@link #glGetMviMatrixf() Mvi} and {@link #glGetMvitMatrixf() Mvit}. + * Returns {@link SyncMatrices4f} of 4 matrices within one FloatBuffer: {@link #getPMat() P}, {@link #getMvMat() Mv}, {@link #getMviMat() Mvi} and {@link #getMvitMat() Mvit}. * <p> * Method enables the Mvi and Mvit matrix update, and performs it's update w/o clearing the modified bits. * </p> @@ -363,14 +439,14 @@ public final class PMVMatrix implements GLMatrixFunc { * @see #update() * @see #clearAllUpdateRequests() */ - public final FloatBuffer glGetPMvMvitMatrixf() { + public final SyncMatrices4f getSyncPMvMvitMat() { requestMask |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ; updateImpl(false); - return matrixPMvMvit; + return matPMvMvitSync; } /** Returns the frustum, derived from projection * modelview */ - public final Frustum glGetFrustum() { + public final Frustum getFrustum() { requestMask |= DIRTY_FRUSTUM; updateImpl(false); return frustum; @@ -379,8 +455,8 @@ public final class PMVMatrix implements GLMatrixFunc { /** * @return the matrix of the current matrix-mode */ - public final FloatBuffer glGetMatrixf() { - return glGetMatrixf(matrixMode); + public final Matrix4f getCurrentMat() { + return getMat(matrixMode); } /** @@ -390,90 +466,93 @@ public final class PMVMatrix implements GLMatrixFunc { * {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE} * @return the named matrix, not a copy! */ - public final FloatBuffer glGetMatrixf(final int matrixName) { + public final Matrix4f getMat(final int matrixName) { switch(matrixName) { case GL_MODELVIEW_MATRIX: case GL_MODELVIEW: - return matrixMv; + return matMv; case GL_PROJECTION_MATRIX: case GL_PROJECTION: - return matrixP; + return matP; case GL_TEXTURE_MATRIX: case GL.GL_TEXTURE: - return matrixTex; + return matTex; default: throw new GLException("unsupported matrixName: "+matrixName); } } + // + // Basic Matrix4f, Vec3f and Vec4f operations similar to GLMatrixFunc + // + /** - * Multiplies the {@link #glGetPMatrixf() P} and {@link #glGetMvMatrixf() Mv} matrix, i.e. + * Multiplies the {@link #getPMat() P} and {@link #getMvMat() Mv} matrix, i.e. * <pre> - * mat4PMv = P x Mv + * result = P x Mv * </pre> - * @param mat4PMv 4x4 matrix storage for result - * @param mat4PMv_offset - * @return given matrix for chaining + * @param result 4x4 matrix storage for result + * @return given result matrix for chaining */ - public final float[] multPMvMatrixf(final float[/*16*/] mat4PMv, final int mat4PMv_offset) { - FloatUtil.multMatrix(matrixArray, mP_offset, matrixArray, mMv_offset, mat4PMv, mat4PMv_offset); - return mat4PMv; + public final Matrix4f mulPMvMat(final Matrix4f result) { + return result.mul(matP, matMv); } /** - * Multiplies the {@link #glGetMvMatrixf() Mv} and {@link #glGetPMatrixf() P} matrix, i.e. + * Multiplies the {@link #getMvMat() Mv} and {@link #getPMat() P} matrix, i.e. * <pre> - * mat4MvP = Mv x P + * result = Mv x P * </pre> - * @param mat4MvP 4x4 matrix storage for result - * @param mat4MvP_offset - * @return given matrix for chaining + * @param result 4x4 matrix storage for result + * @return given result matrix for chaining */ - public final float[] multMvPMatrixf(final float[/*16*/] mat4MvP, final int mat4MvP_offset) { - FloatUtil.multMatrix(matrixArray, mMv_offset, matrixArray, mP_offset, mat4MvP, mat4MvP_offset); - return mat4MvP; + public final Matrix4f mulMvPMat(final Matrix4f result) { + return result.mul(matMv, matP); } /** * v_out = Mv * v_in - * @param v_in float[4] input vector - * @param v_out float[4] output vector + * @param v_in input vector + * @param v_out output vector + * @return given result vector for chaining */ - public final void multMvMatVec4f(final float[/*4*/] v_in, final float[/*4*/] v_out) { - FloatUtil.multMatrixVec(matrixArray, mMv_offset, v_in, v_out); + public final Vec4f mulMvMatVec4f(final Vec4f v_in, final Vec4f v_out) { + return matMv.mulVec4f(v_in, v_out); } /** * v_out = Mv * v_in * - * Affine 3f-vector transformation by 4x4 matrix, see {@link FloatUtil#multMatrixVec3(float[], int, float[], float[])}. + * Affine 3f-vector transformation by 4x4 matrix, see {@link Matrix4f#mulVec3f(Vec3f, Vec3f)}. * - * @param v_in float[3] input vector - * @param v_out float[3] output vector + * @param v_in input vector + * @param v_out output vector + * @return given result vector for chaining */ - public final void multMvMatVec3f(final float[/*3*/] v_in, final float[/*3*/] v_out) { - FloatUtil.multMatrixVec3(matrixArray, mMv_offset, v_in, v_out); + public final Vec3f mulMvMatVec3f(final Vec3f v_in, final Vec3f v_out) { + return matMv.mulVec3f(v_in, v_out); } /** * v_out = P * v_in - * @param v_in float[4] input vector - * @param v_out float[4] output vector + * @param v_in input vector + * @param v_out output vector + * @return given result vector for chaining */ - public final void multPMatVec4f(final float[/*4*/] v_in, final float[/*4*/] v_out) { - FloatUtil.multMatrixVec(matrixArray, v_in, v_out); // mP_offset := 0 + public final Vec4f mulPMatVec4f(final Vec4f v_in, final Vec4f v_out) { + return matP.mulVec4f(v_in, v_out); } /** * v_out = P * v_in * - * Affine 3f-vector transformation by 4x4 matrix, see {@link FloatUtil#multMatrixVec3(float[], int, float[], float[])}. + * Affine 3f-vector transformation by 4x4 matrix, see {@link Matrix4f#mulVec3f(Vec3f, Vec3f)}. * * @param v_in float[3] input vector * @param v_out float[3] output vector */ - public final void multPMatVec3f(final float[/*3*/] v_in, final float[/*3*/] v_out) { - FloatUtil.multMatrixVec3(matrixArray, v_in, v_out); // mP_offset := 0 + public final Vec3f mulPMatVec3f(final Vec3f v_in, final Vec3f v_out) { + return matP.mulVec3f(v_in, v_out); } /** @@ -481,22 +560,20 @@ public final class PMVMatrix implements GLMatrixFunc { * @param v_in float[4] input vector * @param v_out float[4] output vector */ - public final void multPMvMatVec4f(final float[/*4*/] v_in, final float[/*4*/] v_out) { - FloatUtil.multMatrixVec(matrixArray, mMv_offset, v_in, mat4Tmp1); - FloatUtil.multMatrixVec(matrixArray, mat4Tmp1, v_out); // mP_offset := 0 + public final Vec4f mulPMvMatVec4f(final Vec4f v_in, final Vec4f v_out) { + return matP.mulVec4f( matMv.mulVec4f( v_in, vec4Tmp1 ), v_out ); } /** * v_out = P * Mv * v_in * - * Affine 3f-vector transformation by 4x4 matrix, see {@link FloatUtil#multMatrixVec3(float[], int, float[], float[])}. + * Affine 3f-vector transformation by 4x4 matrix, see {@link Matrix4f#mulVec3f(Vec3f, Vec3f)}. * * @param v_in float[3] input vector * @param v_out float[3] output vector */ - public final void multPMvMatVec3f(final float[/*3*/] v_in, final float[/*3*/] v_out) { - FloatUtil.multMatrixVec3(matrixArray, mMv_offset, v_in, mat4Tmp1); - FloatUtil.multMatrixVec3(matrixArray, mat4Tmp1, v_out); // mP_offset := 0 + public final Vec3f mulPMvMatVec3f(final Vec3f v_in, final Vec3f v_out) { + return matP.mulVec3f( matMv.mulVec3f( v_in, vec3Tmp1 ), v_out ); } // @@ -522,9 +599,7 @@ public final class PMVMatrix implements GLMatrixFunc { if(matrixGetName==GL_MATRIX_MODE) { params.put(matrixMode); } else { - final FloatBuffer matrix = glGetMatrixf(matrixGetName); - params.put(matrix); // matrix -> params - matrix.reset(); + getMat(matrixGetName).get(params); // matrix -> params } params.position(pos); } @@ -534,9 +609,7 @@ public final class PMVMatrix implements GLMatrixFunc { if(matrixGetName==GL_MATRIX_MODE) { params[params_offset]=matrixMode; } else { - final FloatBuffer matrix = glGetMatrixf(matrixGetName); - matrix.get(params, params_offset, 16); // matrix -> params - matrix.reset(); + getMat(matrixGetName).get(params, params_offset); // matrix -> params } } @@ -563,18 +636,15 @@ public final class PMVMatrix implements GLMatrixFunc { @Override public final void glLoadMatrixf(final float[] values, final int offset) { if(matrixMode==GL_MODELVIEW) { - matrixMv.put(values, offset, 16); - matrixMv.reset(); + matMv.load(values, offset); dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - matrixP.put(values, offset, 16); - matrixP.reset(); + matP.load(values, offset); dirtyBits |= DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - matrixTex.put(values, offset, 16); - matrixTex.reset(); + matTex.load(values, offset); modifiedBits |= MODIFIED_TEXTURE; } } @@ -583,18 +653,15 @@ public final class PMVMatrix implements GLMatrixFunc { public final void glLoadMatrixf(final java.nio.FloatBuffer m) { final int spos = m.position(); if(matrixMode==GL_MODELVIEW) { - matrixMv.put(m); - matrixMv.reset(); + matMv.load(m); dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - matrixP.put(m); - matrixP.reset(); + matP.load(m); dirtyBits |= DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - matrixTex.put(m); - matrixTex.reset(); + matTex.load(m); modifiedBits |= MODIFIED_TEXTURE; } m.position(spos); @@ -602,85 +669,80 @@ public final class PMVMatrix implements GLMatrixFunc { /** * Load the current matrix with the values of the given {@link Matrix4f}. + * <p> + * Extension to {@link GLMatrixFunc}. + * </p> */ public final void glLoadMatrixf(final Matrix4f m) { if(matrixMode==GL_MODELVIEW) { - m.get(matrixArray, mMv_offset); + matMv.load(m); dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - m.get(matrixArray, mP_offset); + matP.load(m); dirtyBits |= DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - m.get(matrixArray, mTex_offset); + matTex.load(m); modifiedBits |= MODIFIED_TEXTURE; } } /** - * Load the current matrix with the values of the given {@link Quaternion}'s rotation {@link Quaternion#toMatrix(float[], int) matrix representation}. + * Load the current matrix with the values of the given {@link Quaternion}'s rotation {@link Matrix4f#setToRotation(Quaternion) matrix representation}. + * <p> + * Extension to {@link GLMatrixFunc}. + * </p> */ public final void glLoadMatrix(final Quaternion quat) { if(matrixMode==GL_MODELVIEW) { - quat.toMatrix(matrixArray, mMv_offset); - matrixMv.reset(); + matMv.setToRotation(quat); dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - quat.toMatrix(matrixArray, mP_offset); - matrixP.reset(); + matP.setToRotation(quat); dirtyBits |= DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - quat.toMatrix(matrixArray, mTex_offset); - matrixTex.reset(); + matTex.setToRotation(quat); modifiedBits |= MODIFIED_TEXTURE; } } @Override public final void glPopMatrix() { - final FloatStack stack; if(matrixMode==GL_MODELVIEW) { - stack = matrixMvStack; + matMv.pop(); } else if(matrixMode==GL_PROJECTION) { - stack = matrixPStack; + matP.pop(); } else if(matrixMode==GL.GL_TEXTURE) { - stack = matrixTStack; - } else { - throw new InternalError("XXX: mode "+matrixMode); + matTex.pop(); } - stack.position(stack.position() - 16); - glLoadMatrixf(stack.buffer(), stack.position()); } @Override public final void glPushMatrix() { if(matrixMode==GL_MODELVIEW) { - matrixMvStack.putOnTop(matrixMv, 16); - matrixMv.reset(); + matMv.push(); } else if(matrixMode==GL_PROJECTION) { - matrixPStack.putOnTop(matrixP, 16); - matrixP.reset(); + matP.push(); } else if(matrixMode==GL.GL_TEXTURE) { - matrixTStack.putOnTop(matrixTex, 16); - matrixTex.reset(); + matTex.push(); } } @Override public final void glLoadIdentity() { if(matrixMode==GL_MODELVIEW) { - FloatUtil.makeIdentity(matrixArray, mMv_offset); + matMv.loadIdentity(); dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - FloatUtil.makeIdentity(matrixArray, mP_offset); + matP.loadIdentity(); dirtyBits |= DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - FloatUtil.makeIdentity(matrixArray, mTex_offset); + matTex.loadIdentity(); modifiedBits |= MODIFIED_TEXTURE; } } @@ -688,76 +750,133 @@ public final class PMVMatrix implements GLMatrixFunc { @SuppressWarnings("deprecation") @Override public final void glMultMatrixf(final FloatBuffer m) { + final int spos = m.position(); if(matrixMode==GL_MODELVIEW) { - FloatUtil.multMatrix(matrixMv, m); + matMv.mul( mat4Tmp1.load( m ) ); dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - FloatUtil.multMatrix(matrixP, m); + matP.mul( mat4Tmp1.load( m ) ); dirtyBits |= DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - FloatUtil.multMatrix(matrixTex, m); + matTex.mul( mat4Tmp1.load( m ) ); modifiedBits |= MODIFIED_TEXTURE; } + m.position(spos); } @Override public final void glMultMatrixf(final float[] m, final int m_offset) { if(matrixMode==GL_MODELVIEW) { - FloatUtil.multMatrix(matrixArray, mMv_offset, m, m_offset); + matMv.mul( mat4Tmp1.load( m, m_offset ) ); dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - FloatUtil.multMatrix(matrixArray, mP_offset, m, m_offset); + matP.mul( mat4Tmp1.load( m, m_offset ) ); dirtyBits |= DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - FloatUtil.multMatrix(matrixArray, mTex_offset, m, m_offset); + matTex.mul( mat4Tmp1.load( m, m_offset ) ); modifiedBits |= MODIFIED_TEXTURE; } } - public final void glMultMatrixf(final Matrix4f m) { + /** + * Multiply the current matrix: [c] = [c] x [m] + * <p> + * Extension to {@link GLMatrixFunc}. + * </p> + * @param m the right hand Matrix4f + * @return this instance of chaining + */ + public final PMVMatrix glMultMatrixf(final Matrix4f m) { if(matrixMode==GL_MODELVIEW) { - new Matrix4f(matrixArray, mMv_offset).mul(m).get(matrixArray, mMv_offset); + matMv.mul( m ); dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_MODELVIEW; } else if(matrixMode==GL_PROJECTION) { - new Matrix4f(matrixArray, mP_offset).mul(m).get(matrixArray, mP_offset); + matP.mul( m ); dirtyBits |= DIRTY_FRUSTUM ; modifiedBits |= MODIFIED_PROJECTION; } else if(matrixMode==GL.GL_TEXTURE) { - new Matrix4f(matrixArray, mTex_offset).mul(m).get(matrixArray, mTex_offset); + matTex.mul( m ); modifiedBits |= MODIFIED_TEXTURE; } + return this; } @Override public final void glTranslatef(final float x, final float y, final float z) { - glMultMatrixf(FloatUtil.makeTranslation(matrixTxSx, false, x, y, z), 0); + glMultMatrixf( mat4Tmp1.setToTranslation(x, y, z) ); + } + + /** + * Translate the current matrix. + * <p> + * Extension to {@link GLMatrixFunc}. + * </p> + * @param t translation vec3 + * @return this instance of chaining + */ + public final PMVMatrix glTranslatef(final Vec3f t) { + return glMultMatrixf( mat4Tmp1.setToTranslation(t) ); } @Override public final void glScalef(final float x, final float y, final float z) { - glMultMatrixf(FloatUtil.makeScale(matrixTxSx, false, x, y, z), 0); + glMultMatrixf( mat4Tmp1.setToScale(x, y, z) ); + } + + /** + * Scale the current matrix. + * <p> + * Extension to {@link GLMatrixFunc}. + * </p> + * @param s scale vec4f + * @return this instance of chaining + */ + public final PMVMatrix glScalef(final Vec3f s) { + return glMultMatrixf( mat4Tmp1.setToScale(s) ); } @Override public final void glRotatef(final float ang_deg, final float x, final float y, final float z) { - glMultMatrixf(FloatUtil.makeRotationAxis(mat4Tmp1, 0, FloatUtil.adegToRad(ang_deg), x, y, z, mat4Tmp2), 0); + glMultMatrixf( mat4Tmp1.setToRotationAxis(FloatUtil.adegToRad(ang_deg), x, y, z) ); } /** - * Rotate the current matrix with the given {@link Quaternion}'s rotation {@link Quaternion#toMatrix(float[], int) matrix representation}. + * Rotate the current matrix by the given axis and angle in radians. + * <p> + * Consider using {@link #glRotate(Quaternion)} + * </p> + * <p> + * Extension to {@link GLMatrixFunc}. + * </p> + * @param ang_rad angle in radians + * @param axis rotation axis + * @return this instance of chaining + * @see #glRotate(Quaternion) */ - public final void glRotate(final Quaternion quat) { - glMultMatrixf(quat.toMatrix(mat4Tmp1, 0), 0); + public final PMVMatrix glRotatef(final float ang_rad, final Vec3f axis) { + return glMultMatrixf( mat4Tmp1.setToRotationAxis(ang_rad, axis) ); + } + + /** + * Rotate the current matrix with the given {@link Quaternion}'s rotation {@link Matrix4f#setToRotation(Quaternion) matrix representation}. + * <p> + * Extension to {@link GLMatrixFunc}. + * </p> + * @param quat the {@link Quaternion} + * @return this instance of chaining + */ + public final PMVMatrix glRotate(final Quaternion quat) { + return glMultMatrixf( mat4Tmp1.setToRotation(quat) ); } @Override public final void glOrthof(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) { - glMultMatrixf( FloatUtil.makeOrtho(mat4Tmp1, 0, true, left, right, bottom, top, zNear, zFar), 0 ); + glMultMatrixf( mat4Tmp1.setToOrtho(left, right, bottom, top, zNear, zFar) ); } /** @@ -765,11 +884,11 @@ public final class PMVMatrix implements GLMatrixFunc { * * @throws GLException if {@code zNear <= 0} or {@code zFar <= zNear} * or {@code left == right}, or {@code bottom == top}. - * @see FloatUtil#makeFrustum(float[], int, boolean, float, float, float, float, float, float) + * @see Matrix4f#setToFrustum(float, float, float, float, float, float) */ @Override public final void glFrustumf(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) throws GLException { - glMultMatrixf( FloatUtil.makeFrustum(mat4Tmp1, 0, true, left, right, bottom, top, zNear, zFar), 0 ); + glMultMatrixf( mat4Tmp1.setToFrustum(left, right, bottom, top, zNear, zFar) ); } // @@ -784,30 +903,18 @@ public final class PMVMatrix implements GLMatrixFunc { * @param zNear * @param zFar * @throws GLException if {@code zNear <= 0} or {@code zFar <= zNear} - * @see FloatUtil#makePerspective(float[], int, boolean, float, float, float, float) + * @see Matrix4f#setToPerspective(float, float, float, float) */ public final void gluPerspective(final float fovy_deg, final float aspect, final float zNear, final float zFar) throws GLException { - glMultMatrixf( FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy_deg * FloatUtil.PI / 180.0f, aspect, zNear, zFar), 0 ); + glMultMatrixf( mat4Tmp1.setToPerspective(FloatUtil.adegToRad(fovy_deg), aspect, 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(final float eyex, final float eyey, final float eyez, - final float centerx, final float centery, final float centerz, - final float upx, final float upy, final float upz) { - mat4Tmp2[0+0] = eyex; - mat4Tmp2[1+0] = eyey; - mat4Tmp2[2+0] = eyez; - mat4Tmp2[0+4] = centerx; - mat4Tmp2[1+4] = centery; - mat4Tmp2[2+4] = centerz; - mat4Tmp2[0+8] = upx; - mat4Tmp2[1+8] = upy; - mat4Tmp2[2+8] = upz; - glMultMatrixf( - FloatUtil.makeLookAt(mat4Tmp1, 0, mat4Tmp2 /* eye */, 0, mat4Tmp2 /* center */, 4, mat4Tmp2 /* up */, 8, mat4Tmp3), 0); + public final void gluLookAt(final Vec3f eye, final Vec3f center, final Vec3f up) { + glMultMatrixf( mat4Tmp1.setToLookAt(eye, center, up, mat4Tmp2) ); } /** @@ -816,24 +923,13 @@ public final class PMVMatrix implements GLMatrixFunc { * Traditional <code>gluProject</code> implementation. * </p> * - * @param objx - * @param objy - * @param objz - * @param viewport 4 component viewport vector - * @param viewport_offset - * @param win_pos 3 component window coordinate, the result - * @param win_pos_offset + * @param objPos 3 component object coordinate + * @param viewport Rect4i viewport + * @param winPos 3 component window coordinate, the result * @return true if successful, otherwise false (z is 1) */ - public final boolean gluProject(final float objx, final float objy, final float objz, - final int[] viewport, final int viewport_offset, - final float[] win_pos, final int win_pos_offset ) { - return FloatUtil.mapObjToWin(objx, objy, objz, - matrixArray, mMv_offset, - matrixArray, mP_offset, - viewport, viewport_offset, - win_pos, win_pos_offset, - mat4Tmp1, mat4Tmp2); + public final boolean gluProject(final Vec3f objPos, final Recti viewport, final Vec3f winPos ) { + return Matrix4f.mapObjToWin(objPos, matMv, matP, viewport, winPos); } /** @@ -845,21 +941,17 @@ public final class PMVMatrix implements GLMatrixFunc { * @param winx * @param winy * @param winz - * @param viewport 4 component viewport vector - * @param viewport_offset - * @param obj_pos 3 component object coordinate, the result - * @param obj_pos_offset + * @param viewport Rect4i viewport + * @param objPos 3 component object coordinate, the result * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z) */ public final boolean gluUnProject(final float winx, final float winy, final float winz, - final int[] viewport, final int viewport_offset, - final float[] obj_pos, final int obj_pos_offset) { - return FloatUtil.mapWinToObj(winx, winy, winz, - matrixArray, mMv_offset, - matrixArray, mP_offset, - viewport, viewport_offset, - obj_pos, obj_pos_offset, - mat4Tmp1, mat4Tmp2); + final Recti viewport, final Vec3f objPos) { + if( Matrix4f.mapWinToObj(winx, winy, winz, matMv, matP, viewport, objPos, mat4Tmp1) ) { + return true; + } else { + return false; + } } /** @@ -872,29 +964,21 @@ public final class PMVMatrix implements GLMatrixFunc { * @param winy * @param winz * @param clipw - * @param modelMatrix 4x4 modelview matrix - * @param modelMatrix_offset - * @param projMatrix 4x4 projection matrix - * @param projMatrix_offset - * @param viewport 4 component viewport vector - * @param viewport_offset + * @param viewport Rect4i viewport * @param near * @param far - * @param obj_pos 4 component object coordinate, the result - * @param obj_pos_offset + * @param objPos 4 component object coordinate, the result * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z) */ public boolean gluUnProject4(final float winx, final float winy, final float winz, final float clipw, - final int[] viewport, final int viewport_offset, + final Recti viewport, final float near, final float far, - final float[] obj_pos, final int obj_pos_offset ) { - return FloatUtil.mapWinToObj4(winx, winy, winz, clipw, - matrixArray, mMv_offset, - matrixArray, mP_offset, - viewport, viewport_offset, - near, far, - obj_pos, obj_pos_offset, - mat4Tmp1, mat4Tmp2); + final Vec4f objPos) { + if( Matrix4f.mapWinToObj4(winx, winy, winz, clipw, matMv, matP, viewport, near, far, objPos, mat4Tmp1) ) { + return true; + } else { + return false; + } } /** @@ -903,27 +987,25 @@ public final class PMVMatrix implements GLMatrixFunc { * Traditional <code>gluPickMatrix</code> implementation. * </p> * <p> - * See {@link FloatUtil#makePick(float[], int, float, float, float, float, int[], int, float[]) FloatUtil.makePick(..)} for details. + * See {@link Matrix4f#setToPick(float, float, float, float, Recti, int, Matrix4f) for details. * </p> * @param x the center x-component of a picking region in window coordinates * @param y the center y-component of a picking region in window coordinates * @param deltaX the width of the picking region in window coordinates. * @param deltaY the height of the picking region in window coordinates. - * @param viewport 4 component viewport vector - * @param viewport_offset + * @param viewport Rect4i viewport vector */ public final void gluPickMatrix(final float x, final float y, - final float deltaX, final float deltaY, - final int[] viewport, final int viewport_offset) { - if( null != FloatUtil.makePick(mat4Tmp1, 0, x, y, deltaX, deltaY, viewport, viewport_offset, mat4Tmp2) ) { - glMultMatrixf(mat4Tmp1, 0); + final float deltaX, final float deltaY, final Recti viewport) { + if( null != mat4Tmp1.setToPick(x, y, deltaX, deltaY, viewport, mat4Tmp2) ) { + glMultMatrixf( mat4Tmp1 ); } } /** * Map two window coordinates w/ shared X/Y and distinctive Z * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i> - * using a {@link AABBox#getRayIntersection(Ray, float[]) bounding box}. + * using a {@link AABBox#getRayIntersection(Vec3f, Ray, float, boolean) bounding box}. * <p> * Notes for picking <i>winz0</i> and <i>winz1</i>: * <ul> @@ -937,17 +1019,12 @@ public final class PMVMatrix implements GLMatrixFunc { * @param winz0 * @param winz1 * @param viewport - * @param viewport_offset * @param ray storage for the resulting {@link Ray} * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity) */ public final boolean gluUnProjectRay(final float winx, final float winy, final float winz0, final float winz1, - final int[] viewport, - final Ray ray) { - return FloatUtil.mapWinToRay(winx, winy, winz0, winz1, - matrixArray, mMv_offset, - matrixArray, mP_offset, viewport, - ray, mat4Tmp1, mat4Tmp2, mat4Tmp3); + final Recti viewport, final Ray ray) { + return Matrix4f.mapWinToRay(winx, winy, winz0, winz1, matMv, matP, viewport, ray, mat4Tmp1, mat4Tmp2); } public StringBuilder toString(StringBuilder sb, final String f) { @@ -967,18 +1044,18 @@ public final class PMVMatrix implements GLMatrixFunc { sb.append("PMVMatrix[modified[P ").append(modP).append(", Mv ").append(modMv).append(", T ").append(modT); sb.append("], dirty/req[Mvi ").append(mviDirty).append("/").append(mviReq).append(", Mvit ").append(mvitDirty).append("/").append(mvitReq).append(", Frustum ").append(frustumDirty).append("/").append(frustumReq).append("]").append(PlatformPropsImpl.NEWLINE); sb.append(", Projection").append(PlatformPropsImpl.NEWLINE); - matrixToString(sb, f, matrixP); + matP.toString(sb, null, f); sb.append(", Modelview").append(PlatformPropsImpl.NEWLINE); - matrixToString(sb, f, matrixMv); + matMv.toString(sb, null, f); sb.append(", Texture").append(PlatformPropsImpl.NEWLINE); - matrixToString(sb, f, matrixTex); + matTex.toString(sb, null, f); if( 0 != ( requestMask & DIRTY_INVERSE_MODELVIEW ) ) { sb.append(", Inverse Modelview").append(PlatformPropsImpl.NEWLINE); - matrixToString(sb, f, matrixMvi); + matMvi.toString(sb, null, f); } if( 0 != ( requestMask & DIRTY_INVERSE_TRANSPOSED_MODELVIEW ) ) { sb.append(", Inverse Transposed Modelview").append(PlatformPropsImpl.NEWLINE); - matrixToString(sb, f, matrixMvit); + matMvit.toString(sb, null, f); } sb.append("]"); return sb; @@ -1014,18 +1091,18 @@ public final class PMVMatrix implements GLMatrixFunc { * <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. + * has been requested by one of the {@link #getMviMat() Mvi get}, {@link #getMvitMat() Mvit get} + * or {@link #getFrustum() Frustum get} methods. * </p> * * @see #DIRTY_INVERSE_MODELVIEW * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW * @see #DIRTY_FRUSTUM - * @see #glGetMviMatrixf() - * @see #glGetMvitMatrixf() + * @see #getMviMat() + * @see #getMvitMat() * @see #glGetPMvMviMatrixf() * @see #glGetPMvMvitMatrixf() - * @see #glGetFrustum() + * @see #getFrustum() */ public final int getDirtyBits() { return dirtyBits; @@ -1034,19 +1111,19 @@ public final class PMVMatrix implements GLMatrixFunc { /** * 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. + * The request bit mask is set by one of the {@link #getMviMat() Mvi get}, {@link #getMvitMat() Mvit get} + * or {@link #getFrustum() Frustum get} methods. * </p> * * @see #clearAllUpdateRequests() * @see #DIRTY_INVERSE_MODELVIEW * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW * @see #DIRTY_FRUSTUM - * @see #glGetMviMatrixf() - * @see #glGetMvitMatrixf() + * @see #getMviMat() + * @see #getMvitMat() * @see #glGetPMvMviMatrixf() * @see #glGetPMvMvitMatrixf() - * @see #glGetFrustum() + * @see #getFrustum() */ public final int getRequestMask() { return requestMask; @@ -1055,17 +1132,17 @@ public final class PMVMatrix implements GLMatrixFunc { /** * 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. + * after it has been enabled by one of the {@link #getMviMat() Mvi get}, {@link #getMvitMat() Mvit get} + * or {@link #getFrustum() 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 #getMviMat() + * @see #getMvitMat() * @see #glGetPMvMviMatrixf() * @see #glGetPMvMvitMatrixf() - * @see #glGetFrustum() + * @see #getFrustum() * @see #getRequestMask() */ public final void clearAllUpdateRequests() { @@ -1073,20 +1150,20 @@ public final class PMVMatrix implements GLMatrixFunc { } /** - * Update the derived {@link #glGetMviMatrixf() inverse modelview (Mvi)}, - * {@link #glGetMvitMatrixf() inverse transposed modelview (Mvit)} matrices and {@link Frustum} + * Update the derived {@link #getMviMat() inverse modelview (Mvi)}, + * {@link #getMvitMat() inverse transposed modelview (Mvit)} matrices and {@link Frustum} * <b>if</b> they are dirty <b>and</b> they were requested - * by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get} - * or {@link #glGetFrustum() Frustum get} methods. + * by one of the {@link #getMviMat() Mvi get}, {@link #getMvitMat() Mvit get} + * or {@link #getFrustum() 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. + * {@link #getMvMat() Mv matrix} has been modified since their last update. * </p> * <p> * Method should be called manually in case mutable operations has been called * 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. + * {@link #getMviMat() Mvi get}, {@link #getMvitMat() Mvit get} + * or {@link #getFrustum() Frustum get} etc anymore. * </p> * <p> * This method clears the modified bits like {@link #getModifiedBits(boolean) getModifiedBits(true)}, @@ -1106,11 +1183,11 @@ public final class PMVMatrix implements GLMatrixFunc { * @see #DIRTY_INVERSE_MODELVIEW * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW * @see #DIRTY_FRUSTUM - * @see #glGetMviMatrixf() - * @see #glGetMvitMatrixf() + * @see #getMviMat() + * @see #getMvitMat() * @see #glGetPMvMviMatrixf() * @see #glGetPMvMvitMatrixf() - * @see #glGetFrustum() + * @see #getFrustum() * @see #clearAllUpdateRequests() */ public final boolean update() { @@ -1126,9 +1203,8 @@ public final class PMVMatrix implements GLMatrixFunc { if( null == frustum ) { frustum = new Frustum(); } - FloatUtil.multMatrix(matrixArray, mP_offset, matrixArray, mMv_offset, mat4Tmp1, 0); - // FloatUtil.multMatrix(matrixP, matrixMv, mat4Tmp1, 0); - frustum.updateByPMV(mat4Tmp1, 0); + mat4Tmp1.mul(matP, matMv); + frustum.updateFrustumPlanes(mat4Tmp1); dirtyBits &= ~DIRTY_FRUSTUM; mod = true; } @@ -1146,35 +1222,138 @@ public final class PMVMatrix implements GLMatrixFunc { private static final String msgCantComputeInverse = "Invalid source Mv matrix, can't compute inverse"; private final boolean setMviMvit() { - final float[] _matrixMvi = matrixMvi.array(); - final int _matrixMviOffset = matrixMvi.position(); boolean res = false; if( 0 != ( dirtyBits & DIRTY_INVERSE_MODELVIEW ) ) { // only if dirt; always requested at this point, see update() - if( null == FloatUtil.invertMatrix(matrixArray, mMv_offset, _matrixMvi, _matrixMviOffset) ) { + if( !matMvi.invert(matMv) ) { throw new GLException(msgCantComputeInverse); } dirtyBits &= ~DIRTY_INVERSE_MODELVIEW; res = true; } if( 0 != ( requestMask & ( dirtyBits & DIRTY_INVERSE_TRANSPOSED_MODELVIEW ) ) ) { // only if requested & dirty - FloatUtil.transposeMatrix(_matrixMvi, _matrixMviOffset, matrixMvit.array(), matrixMvit.position()); + matMvit.transpose(matMvi); dirtyBits &= ~DIRTY_INVERSE_TRANSPOSED_MODELVIEW; res = true; } return res; } - private static final int mP_offset = 0*16; - private static final int mMv_offset = 1*16; - private static final int mTex_offset = 4*16; - private final float[] matrixArray; - private final FloatBuffer matrixPMvMvit, matrixPMvMvi, matrixPMv, matrixP, matrixTex, matrixMv, matrixMvi, matrixMvit; - private final float[] matrixTxSx; - private final float[] mat4Tmp1, mat4Tmp2, mat4Tmp3; - private final FloatStack matrixTStack, matrixPStack, matrixMvStack; + private final Matrix4f matP; + private final Matrix4f matMv; + private final Matrix4f matMvi; + private final Matrix4f matMvit; + private final Matrix4f matTex; + + private static final int mP_offset = 0*16; + private static final int mMv_offset = 1*16; + private static final int mMvi_offset = 2*16; + private static final int mMvit_offset = 3*16; + private static final int mTex_offset = 4*16; + + private final float[] matrixStore; + private final FloatBuffer matrixP, matrixMv, matrixMvi, matrixMvit, matrixTex; + private final FloatBuffer matrixPMvMvit, matrixPMvMvi, matrixPMv; + + private final SyncMatrix4f matPSync, matMvSync, matMviSync, matMvitSync, matTexSync; + private final SyncMatrices4f matPMvMvitSync, matPMvMviSync, matPMvSync; + + private final Matrix4f mat4Tmp1, mat4Tmp2; + private final Vec3f vec3Tmp1; + private final Vec4f vec4Tmp1; + private int matrixMode = GL_MODELVIEW; private int modifiedBits = MODIFIED_ALL; private int dirtyBits = DIRTY_ALL; // contains the dirty bits, i.e. hinting for update operation private int requestMask = 0; // may contain the requested dirty bits: DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW private Frustum frustum; + + private abstract class PMVSyncBuffer implements SyncMatrix4f { + protected final Matrix4f mat; + private final FloatBuffer fbuf; + + public PMVSyncBuffer(final Matrix4f m, final FloatBuffer fbuf) { + this.mat = m; + this.fbuf = fbuf; + } + + @Override + public final Buffer getBuffer() { return fbuf; } + + @Override + public final SyncBuffer sync() { getAction().sync(); return this; } + + @Override + public final Buffer getSyncBuffer() { getAction().sync(); return fbuf; } + + @Override + public final Matrix4f getMatrix() { return mat; } + + @Override + public final FloatBuffer getSyncFloats() { getAction().sync(); return fbuf; } + } + private final class SyncBuffer0 extends PMVSyncBuffer { + private final SyncAction action = new SyncAction() { + @Override + public void sync() { mat.get(matrixStore); } + }; + + public SyncBuffer0(final Matrix4f m, final FloatBuffer fbuf) { super(m, fbuf); } + + @Override + public SyncAction getAction() { return action; } + + } + private final class SyncBuffer1 extends PMVSyncBuffer { + private final int offset; + private final SyncAction action = new SyncAction() { + @Override + public void sync() { mat.get(matrixStore, offset); } + }; + + public SyncBuffer1(final Matrix4f m, final FloatBuffer fbuf, final int offset) { + super(m, fbuf); + this.offset = offset; + } + + @Override + public SyncAction getAction() { return action; } + } + private final class SyncBufferN implements SyncMatrices4f { + private final Matrix4f[] mats; + private final FloatBuffer fbuf; + private final int offset; + private final SyncAction action = new SyncAction() { + @Override + public void sync() { + int ioff = offset; + for(int i=0; i<mats.length; ++i, ioff+=16) { + mats[i].get(matrixStore, ioff); + } + } + }; + + public SyncBufferN(final Matrix4f[] ms, final FloatBuffer fbuf, final int offset) { + this.mats = ms; + this.fbuf = fbuf; + this.offset = offset; + } + + @Override + public SyncAction getAction() { return action; } + + @Override + public Buffer getBuffer() { return fbuf; } + + @Override + public SyncBuffer sync() { getAction().sync(); return this; } + + @Override + public Buffer getSyncBuffer() { getAction().sync(); return fbuf; } + + @Override + public Matrix4f[] getMatrices() { return mats; } + + @Override + public FloatBuffer getSyncFloats() { getAction().sync(); return fbuf; } + } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/SyncAction.java b/src/jogl/classes/com/jogamp/opengl/util/SyncAction.java new file mode 100644 index 000000000..fbf55e683 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/SyncAction.java @@ -0,0 +1,47 @@ +/** + * Copyright 2023 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: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util; + +/** + * Specific data synchronization action implemented by the data provider + * to update the buffer with the underlying data before usage, e.g. uploading the {@link com.jogamp.opengl.GLUniformData GLUniformData} data to the GPU. + * <p> + * Example: Invoked before delivering {@link com.jogamp.opengl.GLUniformData GLUniformData}'s data via {@link com.jogamp.opengl.GLUniformData#getObject() getObject()} + * or {@link com.jogamp.opengl.GLUniformData#getBuffer() getBuffer()}. + * </p> + */ +public interface SyncAction { + /** + * Synchronizes the buffer with the underlying data before usage. + * <p> + * Example: {@link com.jogamp.opengl.GLUniformData GLUniformData} issues this method before delivering data via {@link com.jogamp.opengl.GLUniformData#getObject() getObject()} + * or {@link com.jogamp.opengl.GLUniformData#getBuffer() getBuffer()}. + * </p> + */ + void sync(); +}
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/opengl/util/SyncBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/SyncBuffer.java new file mode 100644 index 000000000..27bdb5dfb --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/SyncBuffer.java @@ -0,0 +1,61 @@ +/** + * Copyright 2023 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: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util; + +import java.nio.Buffer; + +/** + * Convenient tuple of a {@link SyncAction} and {@link Buffer}. + * <p> + * {@link SyncAction#sync()} is used to update the {@link Buffer} with the underlying data + * known to the data provider. + * </p> + * @see SyncAction + */ +public interface SyncBuffer { + /** + * Return the {@link SyncAction}. + * @see SyncAction + */ + SyncAction getAction(); + + /** Return the {@link Buffer}, i.e. underlying data. */ + Buffer getBuffer(); + + /** + * Synchronizes the underlying data before usage. + * <p> + * Convenient shortcut for {@link #getAction()}.{@link SyncAction#sync() sync()} plus chaining. + * </p> + */ + SyncBuffer sync(); + + /** Return the {@link Buffer} after {@link SyncAction#sync() synchronizing} it. */ + Buffer getSyncBuffer(); + +}
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/opengl/util/SyncMatrices4f.java b/src/jogl/classes/com/jogamp/opengl/util/SyncMatrices4f.java new file mode 100644 index 000000000..055345d65 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/SyncMatrices4f.java @@ -0,0 +1,41 @@ +/** + * Copyright 2023 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: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util; + +import java.nio.FloatBuffer; + +import com.jogamp.opengl.math.Matrix4f; + +/** {@link SyncBuffer} with a multiple underlying {@link Matrix4f}, used in {@link SyncMatrices4f16} and {@link PMVMatrix} */ +public interface SyncMatrices4f extends SyncBuffer { + /** Return the underlying multiple {@link Matrix4f}, used to {@link SyncAction#sync() synchronize} to the {@link #getBuffer()}. */ + Matrix4f[] getMatrices(); + + /** Return the {@link FloatBuffer} after {@link SyncAction#sync() synchronizing} it w/ the underlying {@link #getMatrices()}. */ + FloatBuffer getSyncFloats(); +}
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/opengl/util/SyncMatrices4f16.java b/src/jogl/classes/com/jogamp/opengl/util/SyncMatrices4f16.java new file mode 100644 index 000000000..bca827b9f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/SyncMatrices4f16.java @@ -0,0 +1,74 @@ +/** + * Copyright 2023 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: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util; + +import java.nio.Buffer; +import java.nio.FloatBuffer; + +import com.jogamp.opengl.math.Matrix4f; + +/** {@link SyncBuffer} {@link SyncMatrices4f16} implementation for multiple underlying {@link Matrix4f} instances using one {@code float[16*n]} backing array. */ +public final class SyncMatrices4f16 implements SyncMatrices4f { + private final Matrix4f[] mats; + private final float[] f16s; + private final FloatBuffer fbuf; + private final SyncAction action = new SyncAction() { + @Override + public void sync() { + int ioff = 0; + for(int i=0; i<mats.length; ++i, ioff+=16) { + mats[i].get(f16s, ioff); + } + } + }; + + public SyncMatrices4f16(final Matrix4f[] mats) { + this.mats = mats; + this.f16s = new float[16*mats.length]; + this.fbuf = FloatBuffer.wrap(f16s); + } + + @Override + public SyncAction getAction() { return action; } + + @Override + public Buffer getBuffer() { return fbuf; } + + @Override + public SyncBuffer sync() { getAction().sync(); return this; } + + @Override + public Buffer getSyncBuffer() { getAction().sync(); return fbuf; } + + @Override + public Matrix4f[] getMatrices() { return mats; } + + @Override + public FloatBuffer getSyncFloats() { getAction().sync(); return fbuf; } + +}
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/opengl/util/SyncMatrix4f.java b/src/jogl/classes/com/jogamp/opengl/util/SyncMatrix4f.java new file mode 100644 index 000000000..6ab473771 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/SyncMatrix4f.java @@ -0,0 +1,42 @@ +/** + * Copyright 2023 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: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util; + +import java.nio.FloatBuffer; + +import com.jogamp.opengl.math.Matrix4f; + +/** {@link SyncBuffer} interface with a single underlying {@link Matrix4f}, used in {@link SyncMatrix4f16} and {@link PMVMatrix}. */ +public interface SyncMatrix4f extends SyncBuffer { + /** Return the underlying {@link Matrix4f}, used to {@link SyncAction#sync() synchronize} to the {@link #getBuffer()}. */ + Matrix4f getMatrix(); + + /** Return the {@link FloatBuffer} after {@link SyncAction#sync() synchronizing} it w/ the underlying {@link #getMatrix()}. */ + FloatBuffer getSyncFloats(); + +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/SyncMatrix4f16.java b/src/jogl/classes/com/jogamp/opengl/util/SyncMatrix4f16.java new file mode 100644 index 000000000..03a4b64fa --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/SyncMatrix4f16.java @@ -0,0 +1,74 @@ +/** + * Copyright 2023 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: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util; + +import java.nio.Buffer; +import java.nio.FloatBuffer; + +import com.jogamp.opengl.math.Matrix4f; + +/** {@link SyncBuffer} {@link SyncMatrix4f} implementation for a single underlying {@link Matrix4f} using one {@code float[16]} backing array. */ +public final class SyncMatrix4f16 implements SyncMatrix4f { + private final Matrix4f mat; + private final float[] f16; + private final FloatBuffer fbuf; + private final SyncAction action = new SyncAction() { + @Override + public void sync() { mat.get(f16); } + }; + + public SyncMatrix4f16() { + this.mat = new Matrix4f(); + this.f16 = new float[16]; + this.fbuf = FloatBuffer.wrap(f16); + } + + public SyncMatrix4f16(final Matrix4f m) { + this.mat = m; + this.f16 = new float[16]; + this.fbuf = FloatBuffer.wrap(f16); + } + + @Override + public SyncAction getAction() { return action; } + + @Override + public Buffer getBuffer() { return fbuf; } + + @Override + public SyncBuffer sync() { getAction().sync(); return this; } + + @Override + public Buffer getSyncBuffer() { getAction().sync(); return fbuf; } + + @Override + public Matrix4f getMatrix() { return mat; } + + @Override + public FloatBuffer getSyncFloats() { getAction().sync(); return fbuf; } +}
\ No newline at end of file |