/** * 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.util; 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.math.FloatUtil; import com.jogamp.math.Matrix4f; import com.jogamp.math.Quaternion; import com.jogamp.math.Recti; import com.jogamp.math.Vec3f; import com.jogamp.math.geom.Frustum; import com.jogamp.math.util.PMVMatrix4f; /** * PMVMatrix implements a subset of the fixed function pipeline {@link GLMatrixFunc} * using {@link PMVMatrix4f}. *

* PMVMatrix provides the {@link #getMvi() inverse modelview matrix (Mvi)} and * {@link #getMvit() 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. *

*

* PMVMatrix can supplement {@link com.jogamp.opengl.GL2ES2 GL2ES2} applications w/ the * lack of the described matrix functionality. *

*/ public final class PMVMatrix extends PMVMatrix4f implements GLMatrixFunc { /** * @param matrixModeName One of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE} * @return true if the given matrix-mode name is valid, otherwise false. */ public static final boolean isMatrixModeName(final int matrixModeName) { switch(matrixModeName) { case GL_MODELVIEW_MATRIX: case GL_PROJECTION_MATRIX: case GL_TEXTURE_MATRIX: return true; } return false; } /** * @param matrixModeName One of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE} * @return The corresponding matrix-get name, one of {@link GLMatrixFunc#GL_MODELVIEW_MATRIX GL_MODELVIEW_MATRIX}, {@link GLMatrixFunc#GL_PROJECTION_MATRIX GL_PROJECTION_MATRIX} or {@link GLMatrixFunc#GL_TEXTURE_MATRIX GL_TEXTURE_MATRIX} */ public static final int matrixModeName2MatrixGetName(final int matrixModeName) { switch(matrixModeName) { case GL_MODELVIEW: return GL_MODELVIEW_MATRIX; case GL_PROJECTION: return GL_PROJECTION_MATRIX; case GL.GL_TEXTURE: return GL_TEXTURE_MATRIX; default: throw new GLException("unsupported matrixName: "+matrixModeName); } } /** * @param matrixGetName One of {@link GLMatrixFunc#GL_MODELVIEW_MATRIX GL_MODELVIEW_MATRIX}, {@link GLMatrixFunc#GL_PROJECTION_MATRIX GL_PROJECTION_MATRIX} or {@link GLMatrixFunc#GL_TEXTURE_MATRIX GL_TEXTURE_MATRIX} * @return true if the given matrix-get name is valid, otherwise false. */ public static final boolean isMatrixGetName(final int matrixGetName) { switch(matrixGetName) { case GL_MATRIX_MODE: case GL_MODELVIEW_MATRIX: case GL_PROJECTION_MATRIX: case GL_TEXTURE_MATRIX: return true; } return false; } /** * @param matrixGetName One of {@link GLMatrixFunc#GL_MODELVIEW_MATRIX GL_MODELVIEW_MATRIX}, {@link GLMatrixFunc#GL_PROJECTION_MATRIX GL_PROJECTION_MATRIX} or {@link GLMatrixFunc#GL_TEXTURE_MATRIX GL_TEXTURE_MATRIX} * @return The corresponding matrix-mode name, one of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE} */ public static final int matrixGetName2MatrixModeName(final int matrixGetName) { switch(matrixGetName) { case GL_MODELVIEW_MATRIX: return GL_MODELVIEW; case GL_PROJECTION_MATRIX: return GL_PROJECTION; case GL_TEXTURE_MATRIX: return GL.GL_TEXTURE; default: throw new GLException("unsupported matrixGetName: "+matrixGetName); } } /** * Creates an instance of PMVMatrix. *

* This constructor only sets up an instance w/o additional {@link #INVERSE_MODELVIEW} or {@link #INVERSE_TRANSPOSED_MODELVIEW}. *

*

* Implementation uses non-direct non-NIO Buffers with guaranteed backing array, * which are synchronized to the actual Matrix4f instances. * This allows faster access in Java computation. *

* @see #PMVMatrix(int) */ public PMVMatrix() { this(0); } /** * Creates an instance of PMVMatrix. *

* Additional derived matrices can be requested via `derivedMatrices`, i.e. * - {@link #INVERSE_MODELVIEW} * - {@link #INVERSE_TRANSPOSED_MODELVIEW} *

*

* Implementation uses non-direct non-NIO Buffers with guaranteed backing array, * which are synchronized to the actual Matrix4f instances. * This allows faster access in Java computation. *

* @param derivedMatrices additional matrices can be requested by passing bits {@link #INVERSE_MODELVIEW} and {@link #INVERSE_TRANSPOSED_MODELVIEW}. * @see #getReqBits() * @see #isReqDirty() * @see #getDirtyBits() * @see #update() */ public PMVMatrix(final int derivedMatrices) { super(derivedMatrices); } /** * {@inheritDoc} *

* Leaves {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW} the active matrix mode. *

*/ @Override public void reset() { super.reset(); matrixMode = GL_MODELVIEW; } // // GLMatrixFunc implementation // /** Returns the current matrix-mode, one of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}. */ public final int glGetMatrixMode() { return matrixMode; } /** * @return the matrix of the current matrix-mode */ public final Matrix4f getCurrentMat() { return getMat(matrixMode); } /** * @param matrixName Either a matrix-get-name, i.e. * {@link GLMatrixFunc#GL_MODELVIEW_MATRIX GL_MODELVIEW_MATRIX}, {@link GLMatrixFunc#GL_PROJECTION_MATRIX GL_PROJECTION_MATRIX} or {@link GLMatrixFunc#GL_TEXTURE_MATRIX GL_TEXTURE_MATRIX}, * or a matrix-mode-name, i.e. * {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE} * @return the named matrix, not a copy! */ public final Matrix4f getMat(final int matrixName) { switch(matrixName) { case GL_MODELVIEW_MATRIX: case GL_MODELVIEW: return matMv; case GL_PROJECTION_MATRIX: case GL_PROJECTION: return matP; case GL_TEXTURE_MATRIX: case GL.GL_TEXTURE: return matTex; default: throw new GLException("unsupported matrixName: "+matrixName); } } @Override public final void glMatrixMode(final int matrixName) { switch(matrixName) { case GL_MODELVIEW: case GL_PROJECTION: case GL.GL_TEXTURE: break; default: throw new GLException("unsupported matrixName: "+matrixName); } matrixMode = matrixName; } @Override public final void glGetFloatv(final int matrixGetName, final FloatBuffer params) { final int pos = params.position(); if(matrixGetName==GL_MATRIX_MODE) { params.put(matrixMode); } else { getMat(matrixGetName).get(params); // matrix -> params } params.position(pos); } @Override public final void glGetFloatv(final int matrixGetName, final float[] params, final int params_offset) { if(matrixGetName==GL_MATRIX_MODE) { params[params_offset]=matrixMode; } else { getMat(matrixGetName).get(params, params_offset); // matrix -> params } } @Override public final void glGetIntegerv(final int pname, final IntBuffer params) { final int pos = params.position(); if(pname==GL_MATRIX_MODE) { params.put(matrixMode); } else { throw new GLException("unsupported pname: "+pname); } params.position(pos); } @Override public final void glGetIntegerv(final int pname, final int[] params, final int params_offset) { if(pname==GL_MATRIX_MODE) { params[params_offset]=matrixMode; } else { throw new GLException("unsupported pname: "+pname); } } @Override public final void glLoadMatrixf(final float[] values, final int offset) { if(matrixMode==GL_MODELVIEW) { loadMv(values, offset); } else if(matrixMode==GL_PROJECTION) { loadP(values, offset); } else if(matrixMode==GL.GL_TEXTURE) { loadT(values, offset); } } @Override public final void glLoadMatrixf(final java.nio.FloatBuffer m) { if(matrixMode==GL_MODELVIEW) { loadMv(m); } else if(matrixMode==GL_PROJECTION) { loadP(m); } else if(matrixMode==GL.GL_TEXTURE) { loadT(m); } } /** * Load the current matrix with the values of the given {@link Matrix4f}. *

* Extension to {@link GLMatrixFunc}. *

*/ public final void glLoadMatrixf(final Matrix4f m) { if(matrixMode==GL_MODELVIEW) { loadMv(m); } else if(matrixMode==GL_PROJECTION) { loadP(m); } else if(matrixMode==GL.GL_TEXTURE) { loadT(m); } } /** * Load the current matrix with the values of the given {@link Quaternion}'s rotation {@link Matrix4f#setToRotation(Quaternion) matrix representation}. *

* Extension to {@link GLMatrixFunc}. *

*/ public final void glLoadMatrix(final Quaternion quat) { if(matrixMode==GL_MODELVIEW) { loadMv(quat); } else if(matrixMode==GL_PROJECTION) { loadP(quat); } else if(matrixMode==GL.GL_TEXTURE) { loadT(quat); } } @Override public final void glLoadIdentity() { if(matrixMode==GL_MODELVIEW) { loadMvIdentity(); } else if(matrixMode==GL_PROJECTION) { loadPIdentity(); } else if(matrixMode==GL.GL_TEXTURE) { loadTIdentity(); } } @Override public final void glMultMatrixf(final FloatBuffer m) { final int spos = m.position(); if(matrixMode==GL_MODELVIEW) { mulMv( mat4Tmp1.load( m ) ); } else if(matrixMode==GL_PROJECTION) { mulP( mat4Tmp1.load( m ) ); } else if(matrixMode==GL.GL_TEXTURE) { mulT( mat4Tmp1.load( m ) ); } m.position(spos); } @Override public final void glMultMatrixf(final float[] m, final int m_offset) { if(matrixMode==GL_MODELVIEW) { mulMv( mat4Tmp1.load( m, m_offset ) ); } else if(matrixMode==GL_PROJECTION) { mulP( mat4Tmp1.load( m, m_offset ) ); } else if(matrixMode==GL.GL_TEXTURE) { mulT( mat4Tmp1.load( m, m_offset ) ); } } /** * Multiply the current matrix: [c] = [c] x [m] *

* Extension to {@link GLMatrixFunc}. *

* @param m the right hand Matrix4f * @return this instance of chaining */ public final PMVMatrix glMultMatrixf(final Matrix4f m) { if(matrixMode==GL_MODELVIEW) { mulMv(m); } else if(matrixMode==GL_PROJECTION) { mulP(m); } else if(matrixMode==GL.GL_TEXTURE) { mulT(m); } return this; } @Override public final void glTranslatef(final float x, final float y, final float z) { glMultMatrixf( mat4Tmp1.setToTranslation(x, y, z) ); } /** * Translate the current matrix. *

* Extension to {@link GLMatrixFunc}. *

* @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( mat4Tmp1.setToScale(x, y, z) ); } /** * Scale the current matrix. *

* Extension to {@link GLMatrixFunc}. *

* @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( mat4Tmp1.setToRotationAxis(FloatUtil.adegToRad(ang_deg), x, y, z) ); } /** * Rotate the current matrix by the given axis and angle in radians. *

* Consider using {@link #glRotate(Quaternion)} *

*

* Extension to {@link GLMatrixFunc}. *

* @param ang_rad angle in radians * @param axis rotation axis * @return this instance of chaining * @see #glRotate(Quaternion) */ 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}. *

* Extension to {@link GLMatrixFunc}. *

* @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 glPopMatrix() { if(matrixMode==GL_MODELVIEW) { popMv(); } else if(matrixMode==GL_PROJECTION) { popP(); } else if(matrixMode==GL.GL_TEXTURE) { popT(); } } @Override public final void glPushMatrix() { if(matrixMode==GL_MODELVIEW) { pushMv(); } else if(matrixMode==GL_PROJECTION) { pushP(); } else if(matrixMode==GL.GL_TEXTURE) { pushT(); } } @Override public final void glOrthof(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) { glMultMatrixf( mat4Tmp1.setToOrtho(left, right, bottom, top, zNear, zFar) ); } /** * {@inheritDoc} * * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear} * or {@code left == right}, or {@code bottom == top}. * @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 IllegalArgumentException { glMultMatrixf( mat4Tmp1.setToFrustum(left, right, bottom, top, zNear, zFar) ); } // // Extra functionality // /** * {@link #glMultMatrixf(FloatBuffer) Multiply} the {@link #glGetMatrixMode() current matrix} with the perspective/frustum matrix. * * @param fovy_rad fov angle in radians * @param aspect aspect ratio width / height * @param zNear * @param zFar * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear} * @see Matrix4f#setToPerspective(float, float, float, float) */ public final void gluPerspective(final float fovy_rad, final float aspect, final float zNear, final float zFar) throws IllegalArgumentException { glMultMatrixf( mat4Tmp1.setToPerspective(fovy_rad, aspect, zNear, zFar) ); } /** * {@link #glMultMatrixf(FloatBuffer) Multiply} the {@link #glGetMatrixMode() current matrix} * with the eye, object and orientation, i.e. {@link Matrix4f#setToLookAt(Vec3f, Vec3f, Vec3f, Matrix4f)}. */ public final void gluLookAt(final Vec3f eye, final Vec3f center, final Vec3f up) { glMultMatrixf( mat4Tmp1.setToLookAt(eye, center, up, getTmp2Mat()) ); } /** * Make given matrix the pick matrix based on given parameters. *

* Traditional gluPickMatrix implementation. *

*

* See {@link Matrix4f#setToPick(float, float, float, float, Recti, int, Matrix4f) for details. *

* @param x the center x-component of a picking region in window coordinates * @param y the center y-component of a picking region in window coordinates * @param deltaX the width of the picking region in window coordinates. * @param deltaY the height of the picking region in window coordinates. * @param viewport Rect4i viewport vector */ public final void gluPickMatrix(final float x, final float y, final float deltaX, final float deltaY, final Recti viewport) { if( null != mat4Tmp1.setToPick(x, y, deltaX, deltaY, viewport, getTmp2Mat()) ) { glMultMatrixf( mat4Tmp1 ); } } // // private // private int matrixMode = GL_MODELVIEW; }