diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java | 1628 |
1 files changed, 0 insertions, 1628 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java deleted file mode 100644 index 25b5a8ad7..000000000 --- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java +++ /dev/null @@ -1,1628 +0,0 @@ -/** - * Copyright 2010-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; - -import java.nio.FloatBuffer; -import java.util.Locale; - -import com.jogamp.opengl.GLException; - -import jogamp.opengl.Debug; - -import com.jogamp.common.os.Platform; - -/** - * Basic Float math utility functions. - * <p> - * Implementation assumes linear matrix layout in column-major order - * matching OpenGL's implementation, illustration: - * <pre> - Row-Major Column-Major (OpenGL): - - | 0 1 2 tx | - | | - | 4 5 6 ty | - M = | | - | 8 9 10 tz | - | | - | 12 13 14 15 | - - R C R C - m[0*4+3] = tx; m[0+4*3] = tx; - m[1*4+3] = ty; m[1+4*3] = ty; - m[2*4+3] = tz; m[2+4*3] = tz; - - RC (std subscript order) RC (std subscript order) - m03 = tx; m03 = tx; - m13 = ty; m13 = ty; - m23 = tz; m23 = tz; - - * </pre> - * </p> - * <p> - * <ul> - * <li><a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html">Matrix-FAQ</a></li> - * <li><a href="https://en.wikipedia.org/wiki/Matrix_%28mathematics%29">Wikipedia-Matrix</a></li> - * <li><a href="http://www.euclideanspace.com/maths/algebra/matrix/index.htm">euclideanspace.com-Matrix</a></li> - * </ul> - * </p> - * <p> - * Implementation utilizes unrolling of small vertices and matrices wherever possible - * while trying to access memory in a linear fashion for performance reasons, see: - * <ul> - * <li><a href="https://lessthanoptimal.github.io/Java-Matrix-Benchmark/">java-matrix-benchmark</a></li> - * <li><a href="https://github.com/lessthanoptimal/ejml">EJML Efficient Java Matrix Library</a></li> - * </ul> - * </p> - */ -public final class FloatUtil { - public static final boolean DEBUG = Debug.debugExplicit("Math"); - - // - // 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) - * @return given matrix for chaining - */ - public static float[] makeIdentity(final float[] m) { - m[0+4*0] = 1f; - m[1+4*0] = 0f; - m[2+4*0] = 0f; - m[3+4*0] = 0f; - - m[0+4*1] = 0f; - m[1+4*1] = 1f; - m[2+4*1] = 0f; - m[3+4*1] = 0f; - - m[0+4*2] = 0f; - m[1+4*2] = 0f; - m[2+4*2] = 1f; - m[3+4*2] = 0f; - - m[0+4*3] = 0f; - m[1+4*3] = 0f; - m[2+4*3] = 0f; - m[3+4*3] = 1f; - 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 - * 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 boolean initM, final float tx, final float ty, final float tz) { - if( initM ) { - makeIdentity(m); - } else { - m[0+4*0] = 1; - m[1+4*1] = 1; - m[2+4*2] = 1; - m[3+4*3] = 1; - } - m[0+4*3] = tx; - m[1+4*3] = ty; - m[2+4*3] = tz; - 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 - * 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 boolean initM, final float sx, final float sy, final float sz) { - if( initM ) { - makeIdentity(m); - } else { - m[0+4*3] = 0; - m[1+4*3] = 0; - m[2+4*3] = 0; - m[3+4*3] = 1; - } - m[0+4*0] = sx; - m[1+4*1] = sy; - m[2+4*2] = sz; - return m; - } - - /** - * Make given matrix the frustum matrix based on given parameters. - * <pre> - Frustum matrix (Column Order): - 2*zNear/dx 0 0 0 - 0 2*zNear/dy 0 0 - A B C -1 - 0 0 D 0 - * </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 frustum fields are set. - * @param left - * @param right - * @param bottom - * @param top - * @param zNear - * @param zFar - * @return given matrix for chaining - * @throws GLException if {@code zNear <= 0} or {@code zFar <= zNear} - * or {@code left == right}, or {@code bottom == top}. - */ - public static float[] makeFrustum(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) throws GLException { - if( zNear <= 0.0f || zFar <= zNear ) { - throw new GLException("Requirements zNear > 0 and zFar > zNear, but zNear "+zNear+", zFar "+zFar); - } - if( left == right || top == bottom) { - throw new GLException("GL_INVALID_VALUE: top,bottom and left,right must not be equal"); - } - 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 zNear2 = 2.0f*zNear; - final float dx=right-left; - final float dy=top-bottom; - final float dz=zFar-zNear; - final float A=(right+left)/dx; - final float B=(top+bottom)/dy; - final float C=-1.0f*(zFar+zNear)/dz; - final float D=-2.0f*(zFar*zNear)/dz; - - m[m_offset+0+4*0] = zNear2/dx; - - m[m_offset+1+4*1] = zNear2/dy; - - m[m_offset+0+4*2] = A; - m[m_offset+1+4*2] = B; - m[m_offset+2+4*2] = C; - m[m_offset+3+4*2] = -1.0f; - - m[m_offset+2+4*3] = D; - m[m_offset+3+4*3] = 0f; - - return m; - } - - /** - * Make given matrix the perspective {@link #makeFrustum(float[], int, boolean, float, float, float, float, float, float) frustum} - * matrix based on given parameters. - * <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 frustum fields are set. - * @param fovy_rad angle in radians - * @param aspect aspect ratio width / height - * @param zNear - * @param zFar - * @return given matrix for chaining - * @throws GLException if {@code zNear <= 0} or {@code zFar <= zNear} - * @see #makeFrustum(float[], int, boolean, float, float, float, float, float, float) - */ - public static float[] makePerspective(final float[] m, final int m_off, final boolean initM, - final float fovy_rad, final float aspect, final float zNear, final float zFar) throws GLException { - final float top = tan(fovy_rad/2f) * zNear; // use tangent of half-fov ! - final float bottom = -1.0f * top; // -1f * fovhvTan.top * zNear - final float left = aspect * bottom; // aspect * -1f * fovhvTan.top * zNear - final float right = aspect * top; // aspect * fovhvTan.top * zNear - return makeFrustum(m, m_off, initM, left, right, bottom, top, zNear, zFar); - } - - /** - * Make given matrix the <i>look-at</i> matrix based on given parameters. - * <p> - * Consist out of two matrix multiplications: - * <pre> - * <b>R</b> = <b>L</b> x <b>T</b>, - * with <b>L</b> for <i>look-at</i> matrix and - * <b>T</b> for eye translation. - * - * Result <b>R</b> can be utilized for <i>modelview</i> multiplication, i.e. - * <b>M</b> = <b>M</b> x <b>R</b>, - * with <b>M</b> being the <i>modelview</i> matrix. - * </pre> - * </p> - * <p> - * All matrix fields are set. - * </p> - * @param m 4x4 matrix in column-major order, result only - * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix - * @param eye 3 component eye vector - * @param eye_offset - * @param center 3 component center vector - * @param center_offset - * @param up 3 component up vector - * @param up_offset - * @param mat4Tmp temp float[16] storage - * @return given matrix <code>m</code> for chaining - */ - public static float[] makeLookAt(final float[] m, final int m_offset, - final float[] eye, final int eye_offset, - final float[] center, final int center_offset, - final float[] up, final int up_offset, - final float[] mat4Tmp) { - final int forward_off = 0; - final int side_off = 3; - final int up2_off = 6; - - // forward! - mat4Tmp[0] = center[0+center_offset] - eye[0+eye_offset]; - mat4Tmp[1] = center[1+center_offset] - eye[1+eye_offset]; - mat4Tmp[2] = center[2+center_offset] - eye[2+eye_offset]; - - VectorUtil.normalizeVec3(mat4Tmp); // normalize forward - - /* Side = forward x up */ - VectorUtil.crossVec3(mat4Tmp, side_off, mat4Tmp, forward_off, up, up_offset); - VectorUtil.normalizeVec3(mat4Tmp, side_off); // normalize side - - /* Recompute up as: up = side x forward */ - VectorUtil.crossVec3(mat4Tmp, up2_off, mat4Tmp, side_off, mat4Tmp, forward_off); - - m[m_offset + 0 * 4 + 0] = mat4Tmp[0+side_off]; // side - m[m_offset + 0 * 4 + 1] = mat4Tmp[0+up2_off]; // up2 - m[m_offset + 0 * 4 + 2] = -mat4Tmp[0]; // forward - m[m_offset + 0 * 4 + 3] = 0; - - m[m_offset + 1 * 4 + 0] = mat4Tmp[1+side_off]; // side - m[m_offset + 1 * 4 + 1] = mat4Tmp[1+up2_off]; // up2 - m[m_offset + 1 * 4 + 2] = -mat4Tmp[1]; // forward - m[m_offset + 1 * 4 + 3] = 0; - - m[m_offset + 2 * 4 + 0] = mat4Tmp[2+side_off]; // side - m[m_offset + 2 * 4 + 1] = mat4Tmp[2+up2_off]; // up2 - m[m_offset + 2 * 4 + 2] = -mat4Tmp[2]; // forward - m[m_offset + 2 * 4 + 3] = 0; - - m[m_offset + 3 * 4 + 0] = 0; - m[m_offset + 3 * 4 + 1] = 0; - m[m_offset + 3 * 4 + 2] = 0; - m[m_offset + 3 * 4 + 3] = 1; - - makeTranslation(mat4Tmp, true, -eye[0+eye_offset], -eye[1+eye_offset], -eye[2+eye_offset]); - multMatrix(m, m_offset, mat4Tmp, 0); - - return m; - } - - /** - * Make given matrix 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 #makePick(float[], int, float, float, float, float, int[], int, float[]) makePick} - * and multiply a {@link #makePerspective(float[], int, boolean, float, float, float, float) custom perspective matrix} - * by this pick matrix. Then you may load the result onto the perspective matrix stack. - * </p> - * <p> - * All matrix fields are set. - * </p> - * @param m 4x4 matrix in column-major order, result only - * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix - * @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 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 float x, final float y, - final float deltaX, final float deltaY, - final int[] viewport, final int viewport_offset, - final float[] mat4Tmp) { - if (deltaX <= 0 || deltaY <= 0) { - return null; - } - - /* Translate and scale the picked region to the entire window */ - 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, mat4Tmp); - return m; - } - - /** - * 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 - */ - public static float[] transposeMatrix(final float[] msrc, final float[] mres) { - mres[0] = msrc[0*4]; - mres[1] = msrc[1*4]; - mres[2] = msrc[2*4]; - mres[3] = msrc[3*4]; - - final int i4_1 = 1*4; - mres[0+i4_1] = msrc[1+0*4]; - mres[1+i4_1] = msrc[1+1*4]; - mres[2+i4_1] = msrc[1+2*4]; - mres[3+i4_1] = msrc[1+3*4]; - - final int i4_2 = 2*4; - mres[0+i4_2] = msrc[2+0*4]; - mres[1+i4_2] = msrc[2+1*4]; - mres[2+i4_2] = msrc[2+2*4]; - mres[3+i4_2] = msrc[2+3*4]; - - final int i4_3 = 3*4; - mres[0+i4_3] = msrc[3+0*4]; - mres[1+i4_3] = msrc[3+1*4]; - mres[2+i4_3] = msrc[3+2*4]; - mres[3+i4_3] = msrc[3+3*4]; - - return mres; - } - - /** - * 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) { - float a11 = m[ 1+4*1 ]; - float a21 = m[ 2+4*1 ]; - float a31 = m[ 3+4*1 ]; - float a12 = m[ 1+4*2 ]; - float a22 = m[ 2+4*2 ]; - float a32 = m[ 3+4*2 ]; - float a13 = m[ 1+4*3 ]; - float a23 = m[ 2+4*3 ]; - float a33 = m[ 3+4*3 ]; - - float ret = 0; - ret += m[ 0 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31)); - a11 = m[ 1+4*0 ]; - a21 = m[ 2+4*0 ]; - a31 = m[ 3+4*0 ]; - ret -= m[ 0+4*1 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31)); - a12 = m[ 1+4*1 ]; - a22 = m[ 2+4*1 ]; - a32 = m[ 3+4*1 ]; - ret += m[ 0+4*2 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31)); - a13 = m[ 1+4*2 ]; - a23 = m[ 2+4*2 ]; - a33 = m[ 3+4*2 ]; - 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 mres 4x4 matrix in column-major order, the result - may be <code>msrc</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 float[] mres) { - 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]*scale; - final float a21 = msrc[1+4*0]*scale; - final float a31 = msrc[2+4*0]*scale; - final float a41 = msrc[3+4*0]*scale; - final float a12 = msrc[0+4*1]*scale; - final float a22 = msrc[1+4*1]*scale; - final float a32 = msrc[2+4*1]*scale; - final float a42 = msrc[3+4*1]*scale; - final float a13 = msrc[0+4*2]*scale; - final float a23 = msrc[1+4*2]*scale; - final float a33 = msrc[2+4*2]*scale; - final float a43 = msrc[3+4*2]*scale; - final float a14 = msrc[0+4*3]*scale; - final float a24 = msrc[1+4*3]*scale; - final float a34 = msrc[2+4*3]*scale; - final float a44 = msrc[3+4*3]*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] = m11 * invdet; - mres[1+4*0] = m12 * invdet; - mres[2+4*0] = m13 * invdet; - mres[3+4*0] = m14 * invdet; - mres[0+4*1] = m21 * invdet; - mres[1+4*1] = m22 * invdet; - mres[2+4*1] = m23 * invdet; - mres[3+4*1] = m24 * invdet; - mres[0+4*2] = m31 * invdet; - mres[1+4*2] = m32 * invdet; - mres[2+4*2] = m33 * invdet; - mres[3+4*2] = m34 * invdet; - mres[0+4*3] = m41 * invdet; - mres[1+4*3] = m42 * invdet; - mres[2+4*3] = m43 * invdet; - mres[3+4*3] = m44 * invdet; - return mres; - } - - /** - * Map object coordinates to window coordinates. - * <p> - * Traditional <code>gluProject</code> implementation. - * </p> - * - * @param objx - * @param objy - * @param objz - * @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 win_pos 3 component window coordinate, the result - * @param win_pos_offset - * @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[] modelMatrix, final int modelMatrix_offset, - final float[] projMatrix, final int projMatrix_offset, - final int[] viewport, final int viewport_offset, - final float[] win_pos, final int win_pos_offset, - final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) { - vec4Tmp1[0] = objx; - vec4Tmp1[1] = objy; - vec4Tmp1[2] = objz; - vec4Tmp1[3] = 1.0f; - - // vec4Tmp2 = Mv * o - // vec4Tmp1 = P * vec4Tmp2 - // vec4Tmp1 = P * ( Mv * o ) - // vec4Tmp1 = P * Mv * o - multMatrixVec(modelMatrix, modelMatrix_offset, vec4Tmp1, 0, vec4Tmp2, 0); - multMatrixVec(projMatrix, projMatrix_offset, vec4Tmp2, 0, vec4Tmp1, 0); - - 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+win_pos_offset] = vec4Tmp1[0] * viewport[2+viewport_offset] + viewport[0+viewport_offset]; - win_pos[1+win_pos_offset] = vec4Tmp1[1] * viewport[3+viewport_offset] + viewport[1+viewport_offset]; - win_pos[2+win_pos_offset] = vec4Tmp1[2]; - - return true; - } - - /** - * Map window coordinates to object coordinates. - * <p> - * Traditional <code>gluUnProject</code> implementation. - * </p> - * - * @param winx - * @param winy - * @param winz - * @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 obj_pos 3 component object coordinate, the result - * @param obj_pos_offset - * @param mat4Tmp1 16 component matrix for temp storage - * @param mat4Tmp2 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 float[] modelMatrix, final int modelMatrix_offset, - final float[] projMatrix, final int projMatrix_offset, - final int[] viewport, final int viewport_offset, - final float[] obj_pos, final int obj_pos_offset, - final float[/*16*/] mat4Tmp1, final float[/*16*/] mat4Tmp2) { - // 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; - } - mat4Tmp2[0] = winx; - mat4Tmp2[1] = winy; - mat4Tmp2[2] = winz; - mat4Tmp2[3] = 1.0f; - - // Map x and y from window coordinates - mat4Tmp2[0] = (mat4Tmp2[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; - mat4Tmp2[1] = (mat4Tmp2[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; - - // Map to range -1 to 1 - mat4Tmp2[0] = mat4Tmp2[0] * 2 - 1; - mat4Tmp2[1] = mat4Tmp2[1] * 2 - 1; - mat4Tmp2[2] = mat4Tmp2[2] * 2 - 1; - - final int raw_off = 4; - // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2 - multMatrixVec(mat4Tmp1, 0, mat4Tmp2, 0, mat4Tmp2, raw_off); - - if (mat4Tmp2[3+raw_off] == 0.0) { - return false; - } - - mat4Tmp2[3+raw_off] = 1.0f / mat4Tmp2[3+raw_off]; - - obj_pos[0+obj_pos_offset] = mat4Tmp2[0+raw_off] * mat4Tmp2[3+raw_off]; - obj_pos[1+obj_pos_offset] = mat4Tmp2[1+raw_off] * mat4Tmp2[3+raw_off]; - obj_pos[2+obj_pos_offset] = mat4Tmp2[2+raw_off] * mat4Tmp2[3+raw_off]; - - return true; - } - - /** - * Map window coordinates to object coordinates. - * <p> - * Traditional <code>gluUnProject4</code> implementation. - * </p> - * - * @param winx - * @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 near - * @param far - * @param obj_pos 4 component object coordinate, the result - * @param obj_pos_offset - * @param mat4Tmp1 16 component matrix for temp storage - * @param mat4Tmp2 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 mapWinToObj4(final float winx, final float winy, final float winz, final float clipw, - final float[] modelMatrix, final int modelMatrix_offset, - final float[] projMatrix, final int projMatrix_offset, - final int[] viewport, final int viewport_offset, - final float near, final float far, - final float[] obj_pos, final int obj_pos_offset, - final float[/*16*/] mat4Tmp1, final float[/*16*/] mat4Tmp2) { - // 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; - } - - mat4Tmp2[0] = winx; - mat4Tmp2[1] = winy; - mat4Tmp2[2] = winz; - mat4Tmp2[3] = clipw; - - // Map x and y from window coordinates - mat4Tmp2[0] = (mat4Tmp2[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; - mat4Tmp2[1] = (mat4Tmp2[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; - mat4Tmp2[2] = (mat4Tmp2[2] - near) / (far - near); - - // Map to range -1 to 1 - mat4Tmp2[0] = mat4Tmp2[0] * 2 - 1; - mat4Tmp2[1] = mat4Tmp2[1] * 2 - 1; - mat4Tmp2[2] = mat4Tmp2[2] * 2 - 1; - - final int raw_off = 4; - // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2 - multMatrixVec(mat4Tmp1, 0, mat4Tmp2, 0, mat4Tmp2, raw_off); - - if (mat4Tmp2[3+raw_off] == 0.0) { - return false; - } - - obj_pos[0+obj_pos_offset] = mat4Tmp2[0+raw_off]; - obj_pos[1+obj_pos_offset] = mat4Tmp2[1+raw_off]; - obj_pos[2+obj_pos_offset] = mat4Tmp2[2+raw_off]; - obj_pos[3+obj_pos_offset] = mat4Tmp2[3+raw_off]; - - return true; - } - - /** - * Multiply matrix: [d] = [a] x [b] - * @param a 4x4 matrix in column-major order - * @param b 4x4 matrix in column-major order - * @param d result a*b in column-major order - */ - public static void multMatrix(final float[] a, final int a_off, final float[] b, final int b_off, final float[] d, final int d_off) { - final float b00 = b[b_off+0+0*4]; - final float b10 = b[b_off+1+0*4]; - final float b20 = b[b_off+2+0*4]; - final float b30 = b[b_off+3+0*4]; - final float b01 = b[b_off+0+1*4]; - final float b11 = b[b_off+1+1*4]; - final float b21 = b[b_off+2+1*4]; - final float b31 = b[b_off+3+1*4]; - final float b02 = b[b_off+0+2*4]; - final float b12 = b[b_off+1+2*4]; - final float b22 = b[b_off+2+2*4]; - final float b32 = b[b_off+3+2*4]; - final float b03 = b[b_off+0+3*4]; - final float b13 = b[b_off+1+3*4]; - final float b23 = b[b_off+2+3*4]; - final float b33 = b[b_off+3+3*4]; - - float ai0=a[a_off+ 0*4]; // row-0 of a - float ai1=a[a_off+ 1*4]; - float ai2=a[a_off+ 2*4]; - float ai3=a[a_off+ 3*4]; - d[d_off+ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - d[d_off+ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - d[d_off+ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - d[d_off+ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[a_off+1+0*4]; // row-1 of a - ai1=a[a_off+1+1*4]; - ai2=a[a_off+1+2*4]; - ai3=a[a_off+1+3*4]; - d[d_off+1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - d[d_off+1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - d[d_off+1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - d[d_off+1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[a_off+2+0*4]; // row-2 of a - ai1=a[a_off+2+1*4]; - ai2=a[a_off+2+2*4]; - ai3=a[a_off+2+3*4]; - d[d_off+2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - d[d_off+2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - d[d_off+2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - d[d_off+2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[a_off+3+0*4]; // row-3 of a - ai1=a[a_off+3+1*4]; - ai2=a[a_off+3+2*4]; - ai3=a[a_off+3+3*4]; - d[d_off+3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - d[d_off+3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - d[d_off+3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - d[d_off+3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - } - - /** - * Multiply matrix: [d] = [a] x [b] - * @param a 4x4 matrix in column-major order - * @param b 4x4 matrix in column-major order - * @param d result a*b in column-major order - * @return given result matrix <i>d</i> for chaining - */ - public static float[] multMatrix(final float[] a, final float[] b, final float[] d) { - final float b00 = b[0+0*4]; - final float b10 = b[1+0*4]; - final float b20 = b[2+0*4]; - final float b30 = b[3+0*4]; - final float b01 = b[0+1*4]; - final float b11 = b[1+1*4]; - final float b21 = b[2+1*4]; - final float b31 = b[3+1*4]; - final float b02 = b[0+2*4]; - final float b12 = b[1+2*4]; - final float b22 = b[2+2*4]; - final float b32 = b[3+2*4]; - final float b03 = b[0+3*4]; - final float b13 = b[1+3*4]; - final float b23 = b[2+3*4]; - final float b33 = b[3+3*4]; - - float ai0=a[ 0*4]; // row-0 of a - float ai1=a[ 1*4]; - float ai2=a[ 2*4]; - float ai3=a[ 3*4]; - d[ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - d[ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - d[ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - d[ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[1+0*4]; // row-1 of a - ai1=a[1+1*4]; - ai2=a[1+2*4]; - ai3=a[1+3*4]; - d[1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - d[1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - d[1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - d[1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[2+0*4]; // row-2 of a - ai1=a[2+1*4]; - ai2=a[2+2*4]; - ai3=a[2+3*4]; - d[2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - d[2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - d[2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - d[2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[3+0*4]; // row-3 of a - ai1=a[3+1*4]; - ai2=a[3+2*4]; - ai3=a[3+3*4]; - d[3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - d[3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - d[3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - d[3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - return d; - } - - /** - * Multiply matrix: [a] = [a] x [b] - * @param a 4x4 matrix in column-major order (also result) - * @param b 4x4 matrix in column-major order - */ - public static void multMatrix(final float[] a, final int a_off, final float[] b, final int b_off) { - final float b00 = b[b_off+0+0*4]; - final float b10 = b[b_off+1+0*4]; - final float b20 = b[b_off+2+0*4]; - final float b30 = b[b_off+3+0*4]; - final float b01 = b[b_off+0+1*4]; - final float b11 = b[b_off+1+1*4]; - final float b21 = b[b_off+2+1*4]; - final float b31 = b[b_off+3+1*4]; - final float b02 = b[b_off+0+2*4]; - final float b12 = b[b_off+1+2*4]; - final float b22 = b[b_off+2+2*4]; - final float b32 = b[b_off+3+2*4]; - final float b03 = b[b_off+0+3*4]; - final float b13 = b[b_off+1+3*4]; - final float b23 = b[b_off+2+3*4]; - final float b33 = b[b_off+3+3*4]; - - float ai0=a[a_off+ 0*4]; // row-0 of a - float ai1=a[a_off+ 1*4]; - float ai2=a[a_off+ 2*4]; - float ai3=a[a_off+ 3*4]; - a[a_off+ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - a[a_off+ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - a[a_off+ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - a[a_off+ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[a_off+1+0*4]; // row-1 of a - ai1=a[a_off+1+1*4]; - ai2=a[a_off+1+2*4]; - ai3=a[a_off+1+3*4]; - a[a_off+1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - a[a_off+1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - a[a_off+1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - a[a_off+1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[a_off+2+0*4]; // row-2 of a - ai1=a[a_off+2+1*4]; - ai2=a[a_off+2+2*4]; - ai3=a[a_off+2+3*4]; - a[a_off+2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - a[a_off+2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - a[a_off+2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - a[a_off+2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[a_off+3+0*4]; // row-3 of a - ai1=a[a_off+3+1*4]; - ai2=a[a_off+3+2*4]; - ai3=a[a_off+3+3*4]; - a[a_off+3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - a[a_off+3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - a[a_off+3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - a[a_off+3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - } - - /** - * Multiply matrix: [a] = [a] x [b] - * @param a 4x4 matrix in column-major order (also result) - * @param b 4x4 matrix in column-major order - * @return given result matrix <i>a</i> for chaining - */ - public static float[] multMatrix(final float[] a, final float[] b) { - final float b00 = b[0+0*4]; - final float b10 = b[1+0*4]; - final float b20 = b[2+0*4]; - final float b30 = b[3+0*4]; - final float b01 = b[0+1*4]; - final float b11 = b[1+1*4]; - final float b21 = b[2+1*4]; - final float b31 = b[3+1*4]; - final float b02 = b[0+2*4]; - final float b12 = b[1+2*4]; - final float b22 = b[2+2*4]; - final float b32 = b[3+2*4]; - final float b03 = b[0+3*4]; - final float b13 = b[1+3*4]; - final float b23 = b[2+3*4]; - final float b33 = b[3+3*4]; - - float ai0=a[ 0*4]; // row-0 of a - float ai1=a[ 1*4]; - float ai2=a[ 2*4]; - float ai3=a[ 3*4]; - a[ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - a[ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - a[ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - a[ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[1+0*4]; // row-1 of a - ai1=a[1+1*4]; - ai2=a[1+2*4]; - ai3=a[1+3*4]; - a[1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - a[1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - a[1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - a[1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[2+0*4]; // row-2 of a - ai1=a[2+1*4]; - ai2=a[2+2*4]; - ai3=a[2+3*4]; - a[2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - a[2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - a[2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - a[2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - ai0=a[3+0*4]; // row-3 of a - ai1=a[3+1*4]; - ai2=a[3+2*4]; - ai3=a[3+3*4]; - a[3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ; - a[3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ; - a[3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ; - a[3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ; - - return a; - } - - /** - * Multiply matrix: [d] = [a] x [b] - * @param a 4x4 matrix in column-major order - * @param b 4x4 matrix in column-major order - * @param d result a*b in column-major order - */ - public static void multMatrix(final FloatBuffer a, final FloatBuffer b, final float[] d) { - final int a_off = a.position(); - final int b_off = b.position(); - for (int i = 0; i < 4; i++) { - // one row in column-major order - final int a_off_i = a_off+i; - final float ai0=a.get(a_off_i+0*4), ai1=a.get(a_off_i+1*4), ai2=a.get(a_off_i+2*4), ai3=a.get(a_off_i+3*4); // row-i of a - d[i+0*4] = ai0 * b.get(b_off+0+0*4) + ai1 * b.get(b_off+1+0*4) + ai2 * b.get(b_off+2+0*4) + ai3 * b.get(b_off+3+0*4) ; - d[i+1*4] = ai0 * b.get(b_off+0+1*4) + ai1 * b.get(b_off+1+1*4) + ai2 * b.get(b_off+2+1*4) + ai3 * b.get(b_off+3+1*4) ; - d[i+2*4] = ai0 * b.get(b_off+0+2*4) + ai1 * b.get(b_off+1+2*4) + ai2 * b.get(b_off+2+2*4) + ai3 * b.get(b_off+3+2*4) ; - d[i+3*4] = ai0 * b.get(b_off+0+3*4) + ai1 * b.get(b_off+1+3*4) + ai2 * b.get(b_off+2+3*4) + ai3 * b.get(b_off+3+3*4) ; - } - } - - /** - * Multiply matrix: [a] = [a] x [b] - * @param a 4x4 matrix in column-major order (also result) - * @param b 4x4 matrix in column-major order - */ - public static void multMatrix(final FloatBuffer a, final FloatBuffer b) { - final int a_off = a.position(); - final int b_off = b.position(); - for (int i = 0; i < 4; i++) { - // one row in column-major order - final int a_off_i = a_off+i; - final float ai0=a.get(a_off_i+0*4), ai1=a.get(a_off_i+1*4), ai2=a.get(a_off_i+2*4), ai3=a.get(a_off_i+3*4); // row-i of a - a.put(a_off_i+0*4 , ai0 * b.get(b_off+0+0*4) + ai1 * b.get(b_off+1+0*4) + ai2 * b.get(b_off+2+0*4) + ai3 * b.get(b_off+3+0*4) ); - a.put(a_off_i+1*4 , ai0 * b.get(b_off+0+1*4) + ai1 * b.get(b_off+1+1*4) + ai2 * b.get(b_off+2+1*4) + ai3 * b.get(b_off+3+1*4) ); - a.put(a_off_i+2*4 , ai0 * b.get(b_off+0+2*4) + ai1 * b.get(b_off+1+2*4) + ai2 * b.get(b_off+2+2*4) + ai3 * b.get(b_off+3+2*4) ); - a.put(a_off_i+3*4 , ai0 * b.get(b_off+0+3*4) + ai1 * b.get(b_off+1+3*4) + ai2 * b.get(b_off+2+3*4) + ai3 * b.get(b_off+3+3*4) ); - } - } - - /** - * @param m_in 4x4 matrix in column-major order - * @param m_in_off - * @param v_in 4-component column-vector - * @param v_out m_in * v_in - */ - public static void multMatrixVec(final float[] m_in, final int m_in_off, - final float[] v_in, final int v_in_off, - final float[] v_out, final int v_out_off) { - // (one matrix row in column-major order) X (column vector) - v_out[0 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off ] + v_in[1+v_in_off] * m_in[1*4+m_in_off ] + - v_in[2+v_in_off] * m_in[2*4+m_in_off ] + v_in[3+v_in_off] * m_in[3*4+m_in_off ]; - - final int m_in_off_1 = 1+m_in_off; - v_out[1 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off_1] + v_in[1+v_in_off] * m_in[1*4+m_in_off_1] + - v_in[2+v_in_off] * m_in[2*4+m_in_off_1] + v_in[3+v_in_off] * m_in[3*4+m_in_off_1]; - - final int m_in_off_2 = 2+m_in_off; - v_out[2 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off_2] + v_in[1+v_in_off] * m_in[1*4+m_in_off_2] + - v_in[2+v_in_off] * m_in[2*4+m_in_off_2] + v_in[3+v_in_off] * m_in[3*4+m_in_off_2]; - - final int m_in_off_3 = 3+m_in_off; - v_out[3 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off_3] + v_in[1+v_in_off] * m_in[1*4+m_in_off_3] + - v_in[2+v_in_off] * m_in[2*4+m_in_off_3] + v_in[3+v_in_off] * m_in[3*4+m_in_off_3]; - } - - /** - * @param m_in 4x4 matrix in column-major order - * @param m_in_off - * @param v_in 4-component column-vector - * @param v_out m_in * v_in - */ - public static void multMatrixVec(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 ] + v_in[3] * 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] + v_in[3] * 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] + v_in[3] * m_in[3*4+m_in_off_2]; - - final int m_in_off_3 = 3+m_in_off; - v_out[3] = v_in[0] * m_in[0*4+m_in_off_3] + v_in[1] * m_in[1*4+m_in_off_3] + - v_in[2] * m_in[2*4+m_in_off_3] + v_in[3] * m_in[3*4+m_in_off_3]; - } - - /** - * @param m_in 4x4 matrix in column-major order - * @param m_in_off - * @param v_in 4-component column-vector - * @param v_out m_in * v_in - * @return given result vector <i>v_out</i> for chaining - */ - public static float[] multMatrixVec(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 ] + - v_in[2] * m_in[2*4 ] + v_in[3] * m_in[3*4 ]; - - v_out[1] = v_in[0] * m_in[0*4+1] + v_in[1] * m_in[1*4+1] + - v_in[2] * m_in[2*4+1] + v_in[3] * m_in[3*4+1]; - - v_out[2] = v_in[0] * m_in[0*4+2] + v_in[1] * m_in[1*4+2] + - v_in[2] * m_in[2*4+2] + v_in[3] * m_in[3*4+2]; - - v_out[3] = v_in[0] * m_in[0*4+3] + v_in[1] * m_in[1*4+3] + - v_in[2] * m_in[2*4+3] + v_in[3] * m_in[3*4+3]; - - return v_out; - } - - /** - * @param m_in 4x4 matrix in column-major order - * @param v_in 4-component column-vector - * @param v_out m_in * v_in - */ - public static void multMatrixVec(final FloatBuffer m_in, final float[] v_in, final float[] v_out) { - final int m_in_off = m_in.position(); - for (int i = 0; i < 4; i++) { - // (one matrix row in column-major order) X (column vector) - final int i_m_in_off = i+m_in_off; - v_out[i] = - v_in[0] * m_in.get(0*4+i_m_in_off) + - v_in[1] * m_in.get(1*4+i_m_in_off) + - v_in[2] * m_in.get(2*4+i_m_in_off) + - v_in[3] * m_in.get(3*4+i_m_in_off); - } - } - - /** - * 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 ] + - v_in[2] * m_in[2*4 ] + 1f * m_in[3*4 ]; - - v_out[1] = v_in[0] * m_in[0*4+1] + v_in[1] * m_in[1*4+1] + - v_in[2] * m_in[2*4+1] + 1f * m_in[3*4+1]; - - v_out[2] = v_in[0] * m_in[0*4+2] + v_in[1] * m_in[1*4+2] + - v_in[2] * m_in[2*4+2] + 1f * m_in[3*4+2]; - - return v_out; - } - - /** - * @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 mxn matrix (rows x columns) - * @param aOffset 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) - * @param row row number to print - * @return matrix row string representation - */ - public static StringBuilder matrixRowToString(StringBuilder sb, final String f, - final FloatBuffer a, final int aOffset, - final int rows, final int columns, final boolean rowMajorOrder, final int row) { - if(null == sb) { - sb = new StringBuilder(); - } - final int a0 = aOffset + a.position(); - if(rowMajorOrder) { - for(int c=0; c<columns; c++) { - sb.append( String.format((Locale)null, f+", ", a.get( a0 + row*columns + c ) ) ); - } - } else { - for(int r=0; r<columns; r++) { - sb.append( String.format((Locale)null, f+", ", a.get( a0 + row + r*rows ) ) ); - } - } - return sb; - } - - /** - * @param sb optional passed StringBuilder instance to be used - * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter} - * @param a mxn matrix (rows x columns) - * @param aOffset 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) - * @param row row number to print - * @return matrix row string representation - */ - public static StringBuilder matrixRowToString(StringBuilder sb, final String f, - final float[] a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder, final int row) { - if(null == sb) { - sb = new StringBuilder(); - } - if(rowMajorOrder) { - for(int c=0; c<columns; c++) { - sb.append( String.format((Locale)null, f+", ", a[ aOffset + row*columns + c ] ) ); - } - } else { - for(int r=0; r<columns; r++) { - sb.append( String.format((Locale)null, f+", ", a[ aOffset + row + r*rows ] ) ); - } - } - 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 mxn matrix (rows x columns) - * @param aOffset 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 matrix string representation - */ - public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f, - final FloatBuffer a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder) { - if(null == sb) { - sb = new StringBuilder(); - } - final String prefix = ( null == rowPrefix ) ? "" : rowPrefix; - sb.append(prefix).append("{ "); - for(int i=0; i<rows; i++) { - if( 0 < i ) { - sb.append(prefix).append(" "); - } - matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i); - sb.append(System.lineSeparator()); - } - sb.append(prefix).append("}").append(System.lineSeparator()); - 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 mxn matrix (rows x columns) - * @param aOffset 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 matrix string representation - */ - public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f, - final float[] a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder) { - if(null == sb) { - sb = new StringBuilder(); - } - final String prefix = ( null == rowPrefix ) ? "" : rowPrefix; - sb.append(prefix).append("{ "); - for(int i=0; i<rows; i++) { - if( 0 < i ) { - sb.append(prefix).append(" "); - } - matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i); - sb.append(System.lineSeparator()); - } - sb.append(prefix).append("}").append(System.lineSeparator()); - return sb; - } - - // - // Scalar Ops - // - - @SuppressWarnings("unused") - private static void calculateMachineEpsilonFloat() { - final long t0; - if( DEBUG_EPSILON ) { - t0 = Platform.currentTimeMillis(); - } - float machEps = 1.0f; - int i=0; - do { - machEps /= 2.0f; - i++; - } while (1.0f + (machEps / 2.0f) != 1.0f); - machEpsilon = machEps; - if( DEBUG_EPSILON ) { - final long t1 = Platform.currentTimeMillis(); - System.err.println("MachineEpsilon: "+machEpsilon+", in "+i+" iterations within "+(t1-t0)+" ms"); - } - } - private static volatile boolean machEpsilonAvail = false; - private static float machEpsilon = 0f; - private static final boolean DEBUG_EPSILON = false; - - /** - * Return computed machine Epsilon value. - * <p> - * The machine Epsilon value is computed once. - * </p> - * <p> - * On a reference machine the result was {@link #EPSILON} in 23 iterations. - * </p> - * @see #EPSILON - */ - public static float getMachineEpsilon() { - if( !machEpsilonAvail ) { - synchronized(FloatUtil.class) { - if( !machEpsilonAvail ) { - machEpsilonAvail = true; - calculateMachineEpsilonFloat(); - } - } - } - return machEpsilon; - } - - public static final float E = 2.7182818284590452354f; - - /** The value PI, i.e. 180 degrees in radians. */ - public static final float PI = 3.14159265358979323846f; - - /** The value 2PI, i.e. 360 degrees in radians. */ - public static final float TWO_PI = 2f * PI; - - /** The value PI/2, i.e. 90 degrees in radians. */ - public static final float HALF_PI = PI / 2f; - - /** The value PI/4, i.e. 45 degrees in radians. */ - public static final float QUARTER_PI = PI / 4f; - - /** The value PI^2. */ - public final static float SQUARED_PI = PI * PI; - - /** Converts arc-degree to radians */ - public static float adegToRad(final float arc_degree) { - return arc_degree * PI / 180.0f; - } - - /** Converts radians to arc-degree */ - public static float radToADeg(final float rad) { - return rad * 180.0f / PI; - } - - /** - * Epsilon for floating point {@value}, as once computed via {@link #getMachineEpsilon()} on an AMD-64 CPU. - * <p> - * Definition of machine epsilon guarantees that: - * <pre> - * 1.0f + EPSILON != 1.0f - * </pre> - * In other words: <i>machEps</i> is the maximum relative error of the chosen rounding procedure. - * </p> - * <p> - * A number can be considered zero if it is in the range (or in the set): - * <pre> - * <b>MaybeZeroSet</b> e ]-<i>machEps</i> .. <i>machEps</i>[ <i>(exclusive)</i> - * </pre> - * While comparing floating point values, <i>machEps</i> allows to clip the relative error: - * <pre> - * boolean isZero = afloat < EPSILON; - * boolean isNotZero = afloat >= EPSILON; - * - * boolean isEqual = abs(bfloat - afloat) < EPSILON; - * boolean isNotEqual = abs(bfloat - afloat) >= EPSILON; - * </pre> - * </p> - * @see #isEqual(float, float, float) - * @see #isZero(float, float) - */ - public static final float EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d - - /** - * Inversion Epsilon, used with equals method to determine if two inverted matrices are close enough to be considered equal. - * <p> - * Using {@value}, which is ~100 times {@link FloatUtil#EPSILON}. - * </p> - */ - public static final float INV_DEVIANCE = 1.0E-5f; // FloatUtil.EPSILON == 1.1920929E-7f; double ALLOWED_DEVIANCE: 1.0E-8f - - /** - * Return true if both values are equal w/o regarding an epsilon. - * <p> - * Implementation considers following corner cases: - * <ul> - * <li>NaN == NaN</li> - * <li>+Inf == +Inf</li> - * <li>-Inf == -Inf</li> - * </ul> - * </p> - * @see #isEqual(float, float, float) - */ - public static boolean isEqualRaw(final float a, final float b) { - // Values are equal (Inf, Nan .. ) - return Float.floatToIntBits(a) == Float.floatToIntBits(b); - } - - /** - * Return true if both values are equal, i.e. their absolute delta < <code>epsilon</code>. - * <p> - * Implementation considers following corner cases: - * <ul> - * <li>NaN == NaN</li> - * <li>+Inf == +Inf</li> - * <li>-Inf == -Inf</li> - * </ul> - * </p> - * @see #EPSILON - */ - public static boolean isEqual(final float a, final float b, final float epsilon) { - if ( Math.abs(a - b) < epsilon ) { - return true; - } else { - // Values are equal (Inf, Nan .. ) - return Float.floatToIntBits(a) == Float.floatToIntBits(b); - } - } - - /** - * Return true if both values are equal, i.e. their absolute delta < {@link #EPSILON}. - * <p> - * Implementation considers following corner cases: - * <ul> - * <li>NaN == NaN</li> - * <li>+Inf == +Inf</li> - * <li>-Inf == -Inf</li> - * </ul> - * </p> - * @see #EPSILON - */ - public static boolean isEqual(final float a, final float b) { - if ( Math.abs(a - b) < EPSILON ) { - return true; - } else { - // Values are equal (Inf, Nan .. ) - return Float.floatToIntBits(a) == Float.floatToIntBits(b); - } - } - - /** - * Return true if both values are equal, i.e. their absolute delta < {@link #EPSILON}. - * <p> - * Implementation does not consider corner cases like {@link #isEqual(float, float, float)}. - * </p> - * @see #EPSILON - */ - public static boolean isEqual2(final float a, final float b) { - return Math.abs(a - b) < EPSILON; - } - - /** - * Return true if both values are equal w/o regarding an epsilon. - * <p> - * Implementation considers following corner cases: - * <ul> - * <li>NaN == NaN</li> - * <li>+Inf == +Inf</li> - * <li>-Inf == -Inf</li> - * <li>NaN > 0</li> - * <li>+Inf > -Inf</li> - * </ul> - * </p> - * @see #compare(float, float, float) - */ - public static int compare(final float a, final float b) { - if (a < b) { - return -1; // Neither is NaN, a is smaller - } - if (a > b) { - return 1; // Neither is NaN, a is larger - } - final int aBits = Float.floatToIntBits(a); - final int bBits = Float.floatToIntBits(b); - if( aBits == bBits ) { - return 0; // Values are equal (Inf, Nan .. ) - } else if( aBits < bBits ) { - return -1; // (-0.0, 0.0) or (!NaN, NaN) - } else { - return 1; // ( 0.0, -0.0) or ( NaN, !NaN) - } - } - - /** - * Return true if both values are equal, i.e. their absolute delta < <code>epsilon</code>. - * <p> - * Implementation considers following corner cases: - * <ul> - * <li>NaN == NaN</li> - * <li>+Inf == +Inf</li> - * <li>-Inf == -Inf</li> - * <li>NaN > 0</li> - * <li>+Inf > -Inf</li> - * </ul> - * </p> - * @see #EPSILON - */ - public static int compare(final float a, final float b, final float epsilon) { - if ( Math.abs(a - b) < epsilon ) { - return 0; - } else { - return compare(a, b); - } - } - - /** - * Return true if value is zero, i.e. it's absolute value < <code>epsilon</code>. - * @see #EPSILON - */ - public static boolean isZero(final float a, final float epsilon) { - return Math.abs(a) < epsilon; - } - - /** - * Return true if value is zero, i.e. it's absolute value < {@link #EPSILON}. - * @see #EPSILON - */ - public static boolean isZero(final float a) { - return Math.abs(a) < FloatUtil.EPSILON; - } - - /** - * Invokes {@link Math#abs(float)} - * @param a float to process - * @return absolute value of {@code a} - * @deprecated use {@link Math#abs(float)} directly - */ - @Deprecated - public static float abs(final float a) { return java.lang.Math.abs(a); } - - public static float pow(final float a, final float b) { return (float) java.lang.Math.pow(a, b); } - - public static float sin(final float a) { return (float) java.lang.Math.sin(a); } - - public static float asin(final float a) { return (float) java.lang.Math.asin(a); } - - public static float cos(final float a) { return (float) java.lang.Math.cos(a); } - - public static float acos(final float a) { return (float) java.lang.Math.acos(a); } - - public static float tan(final float a) { return (float) java.lang.Math.tan(a); } - - public static float atan(final float a) { return (float) java.lang.Math.atan(a); } - - public static float atan2(final float y, final float x) { return (float) java.lang.Math.atan2(y, x); } - - public static float sqrt(final float a) { return (float) java.lang.Math.sqrt(a); } - - /** - * Returns resolution of Z buffer of given parameter, - * see <a href="http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html">Love Your Z-Buffer</a>. - * <pre> - * return z * z / ( zNear * (1<<zBits) - z ) - * </pre> - * Examples: - * <pre> - * 1.5256461E-4 = 16 zBits, -0.2 zDist, 0.1 zNear - * 6.1033297E-6 = 16 zBits, -1.0 zDist, 0.1 zNear - * </pre> - * @param zBits number of bits of Z precision, i.e. z-buffer depth - * @param z distance from the eye to the object - * @param zNear distance from eye to near clip plane - * @return smallest resolvable Z separation at this range. - */ - public static float getZBufferEpsilon(final int zBits, final float z, final float zNear) { - return z * z / ( zNear * ( 1 << zBits ) - z ); - } - - /** - * Returns Z buffer value of given parameter, - * see <a href="http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html">Love Your Z-Buffer</a>. - * <pre> - * float a = zFar / ( zFar - zNear ) - * float b = zFar * zNear / ( zNear - zFar ) - * return (int) ( (1<<zBits) * ( a + b / z ) ) - * </pre> - * @param zBits number of bits of Z precision, i.e. z-buffer depth - * @param z distance from the eye to the object - * @param zNear distance from eye to near clip plane - * @param zFar distance from eye to far clip plane - * @return z buffer value - */ - public static int getZBufferValue(final int zBits, final float z, final float zNear, final float zFar) { - final float a = zFar / ( zFar - zNear ); - final float b = zFar * zNear / ( zNear - zFar ); - return (int) ( (1<<zBits) * ( a + b / z ) ); - } - - /** - * Returns orthogonal distance - * (1f/zNear-1f/orthoZ) / (1f/zNear-1f/zFar); - */ - public static float getOrthoWinZ(final float orthoZ, final float zNear, final float zFar) { - return (1f/zNear-1f/orthoZ) / (1f/zNear-1f/zFar); - } - -}
\ No newline at end of file |