From 5d6e8a367c03644740187e500c6de5d3ac039d5e Mon Sep 17 00:00:00 2001
From: Sven Gothel
- * Implementation covers {@link FloatUtil} matrix functionality, exposed in an object oriented manner.
- *
- * Unlike {@link com.jogamp.opengl.util.PMVMatrix PMVMatrix}, this class only represents one single matrix
- * without a complete {@link com.jogamp.opengl.fixedfunc.GLMatrixFunc GLMatrixFunc} implementation.
- *
- * For array operations the layout is expected in column-major order
- * matching OpenGL's implementation, illustration:
- *
- 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;
-
- *
- *
- *
- * Implementation utilizes unrolling of small vertices and matrices wherever possible - * while trying to access memory in a linear fashion for performance reasons, see: - *
- * - * @see com.jogamp.opengl.util.PMVMatrix - * @see FloatUtil - */ -public class Matrix4f { - - /** - * Creates a new identity matrix. - */ - public Matrix4f() { - m00 = m11 = m22 = m33 = 1.0f; - // remaining fields have default init to zero - } - - /** - * Creates a new matrix copying the values of the given {@code src} matrix. - */ - public Matrix4f(final Matrix4f src) { - load(src); - } - - /** - * Creates a new matrix based on given float[4*4] column major order. - * @param m 4x4 matrix in column-major order - */ - public Matrix4f(final float[] m) { - load(m); - } - - /** - * Creates a new matrix based on given float[4*4] column major order. - * @param m 4x4 matrix in column-major order - * @param m_off offset for matrix {@code m} - */ - public Matrix4f(final float[] m, final int m_off) { - 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 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. - *- Translation matrix (Column Order): - 1 0 0 0 - 0 1 0 0 - 0 0 1 0 - 0 0 0 1 - *- * @return this matrix for chaining - */ - public final Matrix4f loadIdentity() { - m00 = m11 = m22 = m33 = 1.0f; - m01 = m02 = m03 = - m10 = m12 = m13 = - m20 = m21 = m23 = - m30 = m31 = m32 = 0.0f; - return this; - } - - /** - * Load the values of the given matrix {@code b} to this matrix. - * @param src the source values - * @return this matrix for chaining - */ - public Matrix4f load(final Matrix4f src) { - m00 = src.m00; m10 = src.m10; m20 = src.m20; m30 = src.m30; - m01 = src.m01; m11 = src.m11; m21 = src.m21; m31 = src.m31; - m02 = src.m02; m12 = src.m12; m22 = src.m22; m32 = src.m32; - m03 = src.m03; m13 = src.m13; m23 = src.m23; m33 = src.m33; - return this; - } - - /** - * Load the values of the given matrix {@code src} to this matrix. - * @param src 4x4 matrix float[16] in column-major order - * @return this matrix for chaining - */ - public Matrix4f load(final float[] src) { - m00 = src[0+0*4]; // column 0 - m10 = src[1+0*4]; - m20 = src[2+0*4]; - m30 = src[3+0*4]; - m01 = src[0+1*4]; // column 1 - m11 = src[1+1*4]; - m21 = src[2+1*4]; - m31 = src[3+1*4]; - m02 = src[0+2*4]; // column 2 - m12 = src[1+2*4]; - m22 = src[2+2*4]; - m32 = src[3+2*4]; - m03 = src[0+3*4]; // column 3 - m13 = src[1+3*4]; - m23 = src[2+3*4]; - m33 = src[3+3*4]; - return this; - } - - /** - * Load the values of the given matrix {@code src} to this matrix. - * @param src 4x4 matrix float[16] in column-major order - * @param src_off offset for matrix {@code src} - * @return this matrix for chaining - */ - public Matrix4f load(final float[] src, final int src_off) { - m00 = src[src_off+0+0*4]; - m10 = src[src_off+1+0*4]; - m20 = src[src_off+2+0*4]; - m30 = src[src_off+3+0*4]; - m01 = src[src_off+0+1*4]; - m11 = src[src_off+1+1*4]; - m21 = src[src_off+2+1*4]; - m31 = src[src_off+3+1*4]; - m02 = src[src_off+0+2*4]; - m12 = src[src_off+1+2*4]; - m22 = src[src_off+2+2*4]; - m32 = src[src_off+3+2*4]; - m03 = src[src_off+0+3*4]; - m13 = src[src_off+1+3*4]; - m23 = src[src_off+2+3*4]; - m33 = src[src_off+3+3*4]; - return this; - } - - /** - * Load the values of the given matrix {@code src} to this matrix. - *
- * Implementation uses relative {@link FloatBuffer#get()}, - * hence caller may want to issue {@link FloatBuffer#reset()} thereafter. - *
- * @param src 4x4 matrix {@link FloatBuffer} in column-major order - * @return this matrix for chaining - */ - public Matrix4f load(final FloatBuffer src) { - m00 = src.get(); - m10 = src.get(); - m20 = src.get(); - m30 = src.get(); - m01 = src.get(); - m11 = src.get(); - m21 = src.get(); - m31 = src.get(); - m02 = src.get(); - m12 = src.get(); - m22 = src.get(); - m32 = src.get(); - m03 = src.get(); - m13 = src.get(); - m23 = src.get(); - m33 = src.get(); - return this; - } - - // - // Read out Matrix via get(..) - // - - /** Gets the {@code i}th component, 0 <= i < 16 */ - public float get(final int i) { - switch (i) { - case 0+4*0: return m00; - case 1+4*0: return m10; - case 2+4*0: return m20; - case 3+4*0: return m30; - - case 0+4*1: return m01; - case 1+4*1: return m11; - case 2+4*1: return m21; - case 3+4*1: return m31; - - case 0+4*2: return m02; - case 1+4*2: return m12; - case 2+4*2: return m22; - case 3+4*2: return m32; - - case 0+4*3: return m03; - case 1+4*3: return m13; - case 2+4*3: return m23; - case 3+4*3: return m33; - - default: throw new IndexOutOfBoundsException(); - } - } - - /** - * Get the named column of the given column-major matrix to v_out. - * @param column named column to copy - * @param v_out the column-vector storage - * @return given result vector v_out for chaining - */ - public Vec4f getColumn(final int column, final Vec4f v_out) { - v_out.set( get(0+column*4), - get(1+column*4), - get(2+column*4), - get(3+column*4) ); - return v_out; - } - - /** - * Get the named column of the given column-major matrix to v_out. - * @param column named column to copy - * @param v_out the column-vector storage - * @return given result vector v_out for chaining - */ - public Vec3f getColumn(final int column, final Vec3f v_out) { - v_out.set( get(0+column*4), - get(1+column*4), - get(2+column*4) ); - return v_out; - } - - /** - * Get the named row of the given column-major matrix to v_out. - * @param row named row to copy - * @param v_out the row-vector storage - * @return given result vector v_out for chaining - */ - public Vec4f getRow(final int row, final Vec4f v_out) { - v_out.set( get(row+0*4), - get(row+1*4), - get(row+2*4), - get(row+3*4) ); - return v_out; - } - - /** - * Get the named row of the given column-major matrix to v_out. - * @param row named row to copy - * @param v_out the row-vector storage - * @return given result vector v_out for chaining - */ - public Vec3f getRow(final int row, final Vec3f v_out) { - v_out.set( get(row+0*4), - get(row+1*4), - get(row+2*4) ); - return v_out; - } - - /** - * Get this matrix into the given float[16] array at {@code dst_off} in column major order. - * - * @param dst float[16] array storage in column major order - * @param dst_off offset - * @return {@code dst} for chaining - */ - public float[] get(final float[] dst, final int dst_off) { - dst[dst_off+0+0*4] = m00; - dst[dst_off+1+0*4] = m10; - dst[dst_off+2+0*4] = m20; - dst[dst_off+3+0*4] = m30; - dst[dst_off+0+1*4] = m01; - dst[dst_off+1+1*4] = m11; - dst[dst_off+2+1*4] = m21; - dst[dst_off+3+1*4] = m31; - dst[dst_off+0+2*4] = m02; - dst[dst_off+1+2*4] = m12; - dst[dst_off+2+2*4] = m22; - dst[dst_off+3+2*4] = m32; - dst[dst_off+0+3*4] = m03; - dst[dst_off+1+3*4] = m13; - dst[dst_off+2+3*4] = m23; - dst[dst_off+3+3*4] = m33; - return dst; - } - - /** - * Get this matrix into the given float[16] array in column major order. - * - * @param dst float[16] array storage in column major order - * @return {@code dst} for chaining - */ - public float[] get(final float[] dst) { - dst[0+0*4] = m00; - dst[1+0*4] = m10; - dst[2+0*4] = m20; - dst[3+0*4] = m30; - dst[0+1*4] = m01; - dst[1+1*4] = m11; - dst[2+1*4] = m21; - dst[3+1*4] = m31; - dst[0+2*4] = m02; - dst[1+2*4] = m12; - dst[2+2*4] = m22; - dst[3+2*4] = m32; - dst[0+3*4] = m03; - dst[1+3*4] = m13; - dst[2+3*4] = m23; - dst[3+3*4] = m33; - return dst; - } - - /** - * Get this matrix into the given {@link FloatBuffer} in column major order. - *- * Implementation uses relative {@link FloatBuffer#put(float)}, - * hence caller may want to issue {@link FloatBuffer#reset()} thereafter. - *
- * - * @param dst {@link FloatBuffer} array storage in column major order - * @return {@code dst} for chaining - */ - public FloatBuffer get(final FloatBuffer dst) { - dst.put( m00 ); - dst.put( m10 ); - dst.put( m20 ); - dst.put( m30 ); - dst.put( m01 ); - dst.put( m11 ); - dst.put( m21 ); - dst.put( m31 ); - dst.put( m02 ); - dst.put( m12 ); - dst.put( m22 ); - dst.put( m32 ); - dst.put( m03 ); - dst.put( m13 ); - dst.put( m23 ); - dst.put( m33 ); - return dst; - } - - // - // Basic matrix operations - // - - /** - * Returns the determinant of this matrix - * @return the matrix determinant - */ - public float determinant() { - float ret = 0; - ret += m00 * ( + m11*(m22*m33 - m23*m32) - m12*(m21*m33 - m23*m31) + m13*(m21*m32 - m22*m31)); - ret -= m01 * ( + m10*(m22*m33 - m23*m32) - m12*(m20*m33 - m23*m30) + m13*(m20*m32 - m22*m30)); - ret += m02 * ( + m10*(m21*m33 - m23*m31) - m11*(m20*m33 - m23*m30) + m13*(m20*m31 - m21*m30)); - ret -= m03 * ( + m10*(m21*m32 - m22*m31) - m11*(m20*m32 - m22*m30) + m12*(m20*m31 - m21*m30)); - return ret; - } - - /** - * Transpose this matrix. - * - * @return this matrix for chaining - */ - public final Matrix4f transpose() { - float tmp; - - tmp = m10; - m10 = m01; - m01 = tmp; - - tmp = m20; - m20 = m02; - m02 = tmp; - - tmp = m30; - m30 = m03; - m03 = tmp; - - tmp = m21; - m21 = m12; - m12 = tmp; - - tmp = m31; - m31 = m13; - m13 = tmp; - - tmp = m32; - m32 = m23; - m23 = tmp; - - return this; - } - - /** - * Transpose the given {@code src} matrix into this matrix. - * - * @param src source 4x4 matrix - * @return this matrix (result) for chaining - */ - public final Matrix4f transpose(final Matrix4f src) { - if( src == this ) { - return transpose(); - } - m00 = src.m00; - m10 = src.m01; - m20 = src.m02; - m30 = src.m03; - - m01 = src.m10; - m11 = src.m11; - m21 = src.m12; - m31 = src.m13; - - m02 = src.m20; - m12 = src.m21; - m22 = src.m22; - m32 = src.m23; - - m03 = src.m30; - m13 = src.m31; - m23 = src.m32; - m33 = src.m33; - return this; - } - - /** - * Invert this matrix. - * @return false if this matrix is singular and inversion not possible, otherwise true - */ - public boolean invert() { - final float scale; - try { - scale = mulScale(); - } catch(final ArithmeticException aex) { - return false; // max was 0 - } - final float a00 = m00*scale; - final float a10 = m10*scale; - final float a20 = m20*scale; - final float a30 = m30*scale; - - final float a01 = m01*scale; - final float a11 = m11*scale; - final float a21 = m21*scale; - final float a31 = m31*scale; - - final float a02 = m02*scale; - final float a12 = m12*scale; - final float a22 = m22*scale; - final float a32 = m32*scale; - - final float a03 = m03*scale; - final float a13 = m13*scale; - final float a23 = m23*scale; - final float a33 = m33*scale; - - final float b00 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31); - final float b01 = -( + a10*(a22*a33 - a23*a32) - a12*(a20*a33 - a23*a30) + a13*(a20*a32 - a22*a30)); - final float b02 = + a10*(a21*a33 - a23*a31) - a11*(a20*a33 - a23*a30) + a13*(a20*a31 - a21*a30); - final float b03 = -( + a10*(a21*a32 - a22*a31) - a11*(a20*a32 - a22*a30) + a12*(a20*a31 - a21*a30)); - - final float b10 = -( + a01*(a22*a33 - a23*a32) - a02*(a21*a33 - a23*a31) + a03*(a21*a32 - a22*a31)); - final float b11 = + a00*(a22*a33 - a23*a32) - a02*(a20*a33 - a23*a30) + a03*(a20*a32 - a22*a30); - final float b12 = -( + a00*(a21*a33 - a23*a31) - a01*(a20*a33 - a23*a30) + a03*(a20*a31 - a21*a30)); - final float b13 = + a00*(a21*a32 - a22*a31) - a01*(a20*a32 - a22*a30) + a02*(a20*a31 - a21*a30); - - final float b20 = + a01*(a12*a33 - a13*a32) - a02*(a11*a33 - a13*a31) + a03*(a11*a32 - a12*a31); - final float b21 = -( + a00*(a12*a33 - a13*a32) - a02*(a10*a33 - a13*a30) + a03*(a10*a32 - a12*a30)); - final float b22 = + a00*(a11*a33 - a13*a31) - a01*(a10*a33 - a13*a30) + a03*(a10*a31 - a11*a30); - final float b23 = -( + a00*(a11*a32 - a12*a31) - a01*(a10*a32 - a12*a30) + a02*(a10*a31 - a11*a30)); - - final float b30 = -( + a01*(a12*a23 - a13*a22) - a02*(a11*a23 - a13*a21) + a03*(a11*a22 - a12*a21)); - final float b31 = + a00*(a12*a23 - a13*a22) - a02*(a10*a23 - a13*a20) + a03*(a10*a22 - a12*a20); - final float b32 = -( + a00*(a11*a23 - a13*a21) - a01*(a10*a23 - a13*a20) + a03*(a10*a21 - a11*a20)); - final float b33 = + a00*(a11*a22 - a12*a21) - a01*(a10*a22 - a12*a20) + a02*(a10*a21 - a11*a20); - - final float det = (a00*b00 + a01*b01 + a02*b02 + a03*b03) / scale; - if( 0 == det ) { - return false; - } - final float invdet = 1.0f / det; - - m00 = b00 * invdet; - m10 = b01 * invdet; - m20 = b02 * invdet; - m30 = b03 * invdet; - - m01 = b10 * invdet; - m11 = b11 * invdet; - m21 = b12 * invdet; - m31 = b13 * invdet; - - m02 = b20 * invdet; - m12 = b21 * invdet; - m22 = b22 * invdet; - m32 = b23 * invdet; - - m03 = b30 * invdet; - m13 = b31 * invdet; - m23 = b32 * invdet; - m33 = b33 * invdet; - return true; - } - - /** - * Invert the {@code src} matrix values into this matrix - * @param src the source matrix, which values are to be inverted - * @return false if {@code src} matrix is singular and inversion not possible, otherwise true - */ - public boolean invert(final Matrix4f src) { - final float scale; - try { - scale = src.mulScale(); - } catch(final ArithmeticException aex) { - return false; // max was 0 - } - final float a00 = src.m00*scale; - final float a10 = src.m10*scale; - final float a20 = src.m20*scale; - final float a30 = src.m30*scale; - - final float a01 = src.m01*scale; - final float a11 = src.m11*scale; - final float a21 = src.m21*scale; - final float a31 = src.m31*scale; - - final float a02 = src.m02*scale; - final float a12 = src.m12*scale; - final float a22 = src.m22*scale; - final float a32 = src.m32*scale; - - final float a03 = src.m03*scale; - final float a13 = src.m13*scale; - final float a23 = src.m23*scale; - final float a33 = src.m33*scale; - - final float b00 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31); - final float b01 = -( + a10*(a22*a33 - a23*a32) - a12*(a20*a33 - a23*a30) + a13*(a20*a32 - a22*a30)); - final float b02 = + a10*(a21*a33 - a23*a31) - a11*(a20*a33 - a23*a30) + a13*(a20*a31 - a21*a30); - final float b03 = -( + a10*(a21*a32 - a22*a31) - a11*(a20*a32 - a22*a30) + a12*(a20*a31 - a21*a30)); - - final float b10 = -( + a01*(a22*a33 - a23*a32) - a02*(a21*a33 - a23*a31) + a03*(a21*a32 - a22*a31)); - final float b11 = + a00*(a22*a33 - a23*a32) - a02*(a20*a33 - a23*a30) + a03*(a20*a32 - a22*a30); - final float b12 = -( + a00*(a21*a33 - a23*a31) - a01*(a20*a33 - a23*a30) + a03*(a20*a31 - a21*a30)); - final float b13 = + a00*(a21*a32 - a22*a31) - a01*(a20*a32 - a22*a30) + a02*(a20*a31 - a21*a30); - - final float b20 = + a01*(a12*a33 - a13*a32) - a02*(a11*a33 - a13*a31) + a03*(a11*a32 - a12*a31); - final float b21 = -( + a00*(a12*a33 - a13*a32) - a02*(a10*a33 - a13*a30) + a03*(a10*a32 - a12*a30)); - final float b22 = + a00*(a11*a33 - a13*a31) - a01*(a10*a33 - a13*a30) + a03*(a10*a31 - a11*a30); - final float b23 = -( + a00*(a11*a32 - a12*a31) - a01*(a10*a32 - a12*a30) + a02*(a10*a31 - a11*a30)); - - final float b30 = -( + a01*(a12*a23 - a13*a22) - a02*(a11*a23 - a13*a21) + a03*(a11*a22 - a12*a21)); - final float b31 = + a00*(a12*a23 - a13*a22) - a02*(a10*a23 - a13*a20) + a03*(a10*a22 - a12*a20); - final float b32 = -( + a00*(a11*a23 - a13*a21) - a01*(a10*a23 - a13*a20) + a03*(a10*a21 - a11*a20)); - final float b33 = + a00*(a11*a22 - a12*a21) - a01*(a10*a22 - a12*a20) + a02*(a10*a21 - a11*a20); - - final float det = (a00*b00 + a01*b01 + a02*b02 + a03*b03) / scale; - - if( 0 == det ) { - return false; - } - final float invdet = 1.0f / det; - - m00 = b00 * invdet; - m10 = b01 * invdet; - m20 = b02 * invdet; - m30 = b03 * invdet; - - m01 = b10 * invdet; - m11 = b11 * invdet; - m21 = b12 * invdet; - m31 = b13 * invdet; - - m02 = b20 * invdet; - m12 = b21 * invdet; - m22 = b22 * invdet; - m32 = b23 * invdet; - - m03 = b30 * invdet; - m13 = b31 * invdet; - m23 = b32 * invdet; - m33 = b33 * invdet; - return true; - } - - private final float mulScale() { - /** - // No Hotspot intrinsic Math.* optimization for at least Math.max(), - // hence this chunk is slower. - float max = Math.abs(m00); - - max = Math.max(max, Math.abs(m01)); - max = Math.max(max, Math.abs(m02)); - ... etc - */ - float a = Math.abs(m00); - float max = a; - a = Math.abs(m01); if( a > max ) max = a; - a = Math.abs(m02); if( a > max ) max = a; - a = Math.abs(m03); if( a > max ) max = a; - - a = Math.abs(m10); if( a > max ) max = a; - a = Math.abs(m11); if( a > max ) max = a; - a = Math.abs(m12); if( a > max ) max = a; - a = Math.abs(m13); if( a > max ) max = a; - - a = Math.abs(m20); if( a > max ) max = a; - a = Math.abs(m21); if( a > max ) max = a; - a = Math.abs(m22); if( a > max ) max = a; - a = Math.abs(m23); if( a > max ) max = a; - - a = Math.abs(m30); if( a > max ) max = a; - a = Math.abs(m31); if( a > max ) max = a; - a = Math.abs(m32); if( a > max ) max = a; - a = Math.abs(m33); if( a > max ) max = a; - - return 1.0f/max; - } - - /** - * Multiply matrix: [this] = [this] x [b] - * @param b 4x4 matrix - * @return this matrix for chaining - * @see #mul(Matrix4f, Matrix4f) - */ - public final Matrix4f mul(final Matrix4f b) { - // return mul(new Matrix4f(this), b); // <- roughly half speed - float ai0=m00; // row-0, m[0+0*4] - float ai1=m01; - float ai2=m02; - float ai3=m03; - m00 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ; - m01 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ; - m02 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ; - m03 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ; - - ai0=m10; //row-1, m[1+0*4] - ai1=m11; - ai2=m12; - ai3=m13; - m10 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ; - m11 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ; - m12 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ; - m13 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ; - - ai0=m20; // row-2, m[2+0*4] - ai1=m21; - ai2=m22; - ai3=m23; - m20 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ; - m21 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ; - m22 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ; - m23 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ; - - ai0=m30; // row-3, m[3+0*4] - ai1=m31; - ai2=m32; - ai3=m33; - m30 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ; - m31 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ; - m32 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ; - m33 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ; - return this; - } - - /** - * Multiply matrix: [this] = [a] x [b] - * @param a 4x4 matrix, can't be this matrix - * @param b 4x4 matrix, can't be this matrix - * @return this matrix for chaining - * @see #mul(Matrix4f) - */ - public final Matrix4f mul(final Matrix4f a, final Matrix4f b) { - // row-0, m[0+0*4] - m00 = a.m00 * b.m00 + a.m01 * b.m10 + a.m02 * b.m20 + a.m03 * b.m30 ; - m01 = a.m00 * b.m01 + a.m01 * b.m11 + a.m02 * b.m21 + a.m03 * b.m31 ; - m02 = a.m00 * b.m02 + a.m01 * b.m12 + a.m02 * b.m22 + a.m03 * b.m32 ; - m03 = a.m00 * b.m03 + a.m01 * b.m13 + a.m02 * b.m23 + a.m03 * b.m33 ; - - //row-1, m[1+0*4] - m10 = a.m10 * b.m00 + a.m11 * b.m10 + a.m12 * b.m20 + a.m13 * b.m30 ; - m11 = a.m10 * b.m01 + a.m11 * b.m11 + a.m12 * b.m21 + a.m13 * b.m31 ; - m12 = a.m10 * b.m02 + a.m11 * b.m12 + a.m12 * b.m22 + a.m13 * b.m32 ; - m13 = a.m10 * b.m03 + a.m11 * b.m13 + a.m12 * b.m23 + a.m13 * b.m33 ; - - // row-2, m[2+0*4] - m20 = a.m20 * b.m00 + a.m21 * b.m10 + a.m22 * b.m20 + a.m23 * b.m30 ; - m21 = a.m20 * b.m01 + a.m21 * b.m11 + a.m22 * b.m21 + a.m23 * b.m31 ; - m22 = a.m20 * b.m02 + a.m21 * b.m12 + a.m22 * b.m22 + a.m23 * b.m32 ; - m23 = a.m20 * b.m03 + a.m21 * b.m13 + a.m22 * b.m23 + a.m23 * b.m33 ; - - // row-3, m[3+0*4] - m30 = a.m30 * b.m00 + a.m31 * b.m10 + a.m32 * b.m20 + a.m33 * b.m30 ; - m31 = a.m30 * b.m01 + a.m31 * b.m11 + a.m32 * b.m21 + a.m33 * b.m31 ; - m32 = a.m30 * b.m02 + a.m31 * b.m12 + a.m32 * b.m22 + a.m33 * b.m32 ; - m33 = a.m30 * b.m03 + a.m31 * b.m13 + a.m32 * b.m23 + a.m33 * b.m33 ; - - return this; - } - - /** - * @param v_in 4-component column-vector, can be v_out for in-place transformation - * @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(); - v_out.set( x * m00 + y * m01 + z * m02 + w * m03, - x * m10 + y * m11 + z * m12 + w * m13, - x * m20 + y * m21 + z * m22 + w * m23, - x * m30 + y * m31 + z * m32 + w * m33 ); - return v_out; - } - - /** - * @param v_inout 4-component column-vector input and output, i.e. in-place transformation - * @returns v_inout for chaining - */ - public final Vec4f mulVec4f(final Vec4f v_inout) { - // (one matrix row in column-major order) X (column vector) - final float x = v_inout.x(), y = v_inout.y(), z = v_inout.z(), w = v_inout.w(); - v_inout.set( x * m00 + y * m01 + z * m02 + w * m03, - x * m10 + y * m11 + z * m12 + w * m13, - x * m20 + y * m21 + z * m22 + w * m23, - x * m30 + y * m31 + z * m32 + w * m33 ); - return v_inout; - } - - /** - * 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}. - * - * @param v_in 3-component column-vector {@link Vec3f}, can be v_out for in-place transformation - * @param v_out m_in * v_in, 3-component column-vector {@link Vec3f} - * @returns v_out for chaining - */ - public final Vec3f mulVec3f(final Vec3f v_in, final Vec3f 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(); - v_out.set( x * m00 + y * m01 + z * m02 + 1f * m03, - x * m10 + y * m11 + z * m12 + 1f * m13, - 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_inout.w()} and dropping {@code v_inout.w()}, - * which shall be {@code 1}. - * - * @param v_inout 3-component column-vector {@link Vec3f} input and output, i.e. in-place transformation - * @returns v_inout for chaining - */ - public final Vec3f mulVec3f(final Vec3f v_inout) { - // (one matrix row in column-major order) X (column vector) - final float x = v_inout.x(), y = v_inout.y(), z = v_inout.z(); - v_inout.set( x * m00 + y * m01 + z * m02 + 1f * m03, - x * m10 + y * m11 + z * m12 + 1f * m13, - x * m20 + y * m21 + z * m22 + 1f * m23 ); - return v_inout; - } - - // - // Matrix setTo...(), affine + basic - // - - /** - * Set this matrix to translation. - *- Translation matrix (Column Order): - 1 0 0 0 - 0 1 0 0 - 0 0 1 0 - x y z 1 - *- * @param x x-axis translate - * @param y y-axis translate - * @param z z-axis translate - * @return this matrix for chaining - */ - public final Matrix4f setToTranslation(final float x, final float y, final float z) { - m00 = m11 = m22 = m33 = 1.0f; - m03 = x; - m13 = y; - m23 = z; - m01 = m02 = - m10 = m12 = - m20 = m21 = - m30 = m31 = m32 = 0.0f; - return this; - } - - /** - * Set this matrix to translation. - *
- Translation matrix (Column Order): - 1 0 0 0 - 0 1 0 0 - 0 0 1 0 - x y z 1 - *- * @param t translate Vec3f - * @return this matrix for chaining - */ - public final Matrix4f setToTranslation(final Vec3f t) { - return setToTranslation(t.x(), t.y(), t.z()); - } - - /** - * Set this matrix to scale. - *
- Scale matrix (Any Order): - x 0 0 0 - 0 y 0 0 - 0 0 z 0 - 0 0 0 1 - *- * @param x x-axis scale - * @param y y-axis scale - * @param z z-axis scale - * @return this matrix for chaining - */ - public final Matrix4f setToScale(final float x, final float y, final float z) { - m33 = 1.0f; - m00 = x; - m11 = y; - m22 = z; - m01 = m02 = m03 = - m10 = m12 = m13 = - m20 = m21 = m23 = - m30 = m31 = m32 = 0.0f; - return this; - } - - /** - * Set this matrix to scale. - *
- Scale matrix (Any Order): - x 0 0 0 - 0 y 0 0 - 0 0 z 0 - 0 0 0 1 - *- * @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. - *
- 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 - *- * @see Matrix-FAQ Q38 - * @param ang_rad angle in radians - * @param x x of rotation axis - * @param y y of rotation axis - * @param z z of rotation axis - * @return this matrix for chaining - */ - public final Matrix4f setToRotationAxis(final float ang_rad, float x, float y, float z) { - final float c = FloatUtil.cos(ang_rad); - final float ic= 1.0f - c; - final float s = FloatUtil.sin(ang_rad); - - 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; - final float xs = x*s; - final float ys = y*s; - final float yz = y*z; - final float zs = z*s; - m00 = x*x*ic+c; - m10 = xy*ic+zs; - m20 = xz*ic-ys; - m30 = 0; - - m01 = xy*ic-zs; - m11 = y*y*ic+c; - m21 = yz*ic+xs; - m31 = 0; - - m02 = xz*ic+ys; - m12 = yz*ic-xs; - m22 = z*z*ic+c; - m32 = 0; - - m03 = 0f; - m13 = 0f; - m23 = 0f; - m33 = 1f; - - return this; - } - - /** - * Set this matrix to rotation from the given axis and angle in radians. - *
- 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 - *- * @see Matrix-FAQ Q38 - * @param ang_rad angle in radians - * @param axis rotation axis - * @return this matrix for chaining - */ - public final Matrix4f setToRotationAxis(final float ang_rad, final Vec3f axis) { - return setToRotationAxis(ang_rad, axis.x(), axis.y(), axis.z()); - } - - /** - * Set this matrix to rotation from the given Euler rotation angles in radians. - *
- * The rotations are applied in the given order: - *
- * Implementation does not use Quaternion and hence is exposed to - * Gimbal-Lock, - * consider using {@link #setToRotation(Quaternion)}. - *
- * @see Matrix-FAQ Q36 - * @see euclideanspace.com-eulerToMatrix - * @see #setToRotation(Quaternion) - */ - public Matrix4f setToRotationEuler(final float bankX, final float headingY, final float attitudeZ) { - // Assuming the angles are in radians. - final float ch = FloatUtil.cos(headingY); - final float sh = FloatUtil.sin(headingY); - final float ca = FloatUtil.cos(attitudeZ); - final float sa = FloatUtil.sin(attitudeZ); - final float cb = FloatUtil.cos(bankX); - final float sb = FloatUtil.sin(bankX); - - m00 = ch*ca; - m10 = sa; - m20 = -sh*ca; - m30 = 0; - - m01 = sh*sb - ch*sa*cb; - m11 = ca*cb; - m21 = sh*sa*cb + ch*sb; - m31 = 0; - - m02 = ch*sa*sb + sh*cb; - m12 = -ca*sb; - m22 = -sh*sa*sb + ch*cb; - m32 = 0; - - m03 = 0; - m13 = 0; - m23 = 0; - m33 = 1; - - return this; - } - - /** - * Set this matrix to rotation from the given Euler rotation angles in radians. - *- * The rotations are applied in the given order: - *
- * Implementation does not use Quaternion and hence is exposed to - * Gimbal-Lock, - * consider using {@link #setToRotation(Quaternion)}. - *
- * @see Matrix-FAQ Q36 - * @see euclideanspace.com-eulerToMatrix - * @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. - *- * Implementation Details: - *
- Ortho matrix (Column Order): - 2/dx 0 0 0 - 0 2/dy 0 0 - 0 0 2/dz 0 - tx ty tz 1 - *- * @param left - * @param right - * @param bottom - * @param top - * @param zNear - * @param zFar - * @return this matrix for chaining - */ - public Matrix4f setToOrtho(final float left, final float right, - final float bottom, final float top, - final float zNear, final float zFar) { - { - // m00 = m11 = m22 = m33 = 1f; - m10 = m20 = m30 = 0f; - m01 = m21 = m31 = 0f; - m02 = m12 = m32 = 0f; - // m03 = m13 = m23 = 0f; - } - 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; - - m00 = 2.0f/dx; - m11 = 2.0f/dy; - m22 = -2.0f/dz; - - m03 = tx; - m13 = ty; - m23 = tz; - m33 = 1f; - - return this; - } - - /** - * Set this matrix to frustum. - *
- Frustum matrix (Column Order): - 2*zNear/dx 0 0 0 - 0 2*zNear/dy 0 0 - A B C -1 - 0 0 D 0 - *- * @param left - * @param right - * @param bottom - * @param top - * @param zNear - * @param zFar - * @return this matrix for chaining - * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear} - * or {@code left == right}, or {@code bottom == top}. - */ - public Matrix4f setToFrustum(final float left, final float right, - final float bottom, final float top, - final float zNear, final float zFar) throws IllegalArgumentException { - if( zNear <= 0.0f || zFar <= zNear ) { - throw new IllegalArgumentException("Requirements zNear > 0 and zFar > zNear, but zNear "+zNear+", zFar "+zFar); - } - if( left == right || top == bottom) { - throw new IllegalArgumentException("GL_INVALID_VALUE: top,bottom and left,right must not be equal"); - } - { - // m00 = m11 = m22 = m33 = 1f; - m10 = m20 = m30 = 0f; - m01 = m21 = m31 = 0f; - m03 = m13 = 0f; - } - 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; - - m00 = zNear2/dx; - m11 = zNear2/dy; - - m02 = A; - m12 = B; - m22 = C; - m32 = -1.0f; - - m23 = D; - m33 = 0f; - - return this; - } - - /** - * Set this matrix to perspective {@link #setToFrustum(float, float, float, float, float, float) frustum} projection. - * - * @param fovy_rad angle in radians - * @param aspect aspect ratio width / height - * @param zNear - * @param zFar - * @return this matrix for chaining - * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear} - * @see #setToFrustum(float, float, float, float, float, float) - */ - public Matrix4f setToPerspective(final float fovy_rad, final float aspect, final float zNear, final float zFar) throws IllegalArgumentException { - final float top = FloatUtil.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 setToFrustum(left, right, bottom, top, zNear, zFar); - } - - /** - * Set this matrix to perspective {@link #setToFrustum(float, float, float, float, float, float) frustum} projection. - * - * @param fovhv {@link FovHVHalves} field of view in both directions, may not be centered, either in radians or tangent - * @param zNear - * @param zFar - * @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(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 ! - final float top = fovhvTan.top * zNear; - final float bottom = -1.0f * fovhvTan.bottom * zNear; - final float left = -1.0f * fovhvTan.left * zNear; - final float right = fovhvTan.right * zNear; - return setToFrustum(left, right, bottom, top, zNear, zFar); - } - - /** - * Calculate the frustum planes in world coordinates - * using this premultiplied P*MV (column major order) matrix. - *
- * Frustum plane's normals will point to the inside of the viewing frustum, - * as required by this class. - *
- *- * Usually called by {@link Frustum#updateFrustumPlanes(Matrix4f)}. - *
- */ - public void updateFrustumPlanes(final Frustum frustum) { - // 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 Frustum.Plane p = frustum.getPlanes()[Frustum.LEFT]; - final Vec3f p_n = p.n; - p_n.set( m30 + m00, - m31 + m01, - m32 + m02 ); - p.d = m33 + m03; - } - - // 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 Frustum.Plane p = frustum.getPlanes()[Frustum.RIGHT]; - final Vec3f p_n = p.n; - p_n.set( m30 - m00, - m31 - m01, - m32 - m02 ); - p.d = m33 - m03; - } - - // Bottom: a = m41m21, b = m42m22, c = m43m23, d = m44m24 - [1..4] column-major - // Bottom: a = m30m10, b = m31m11, c = m32m12, d = m33m13 - [0..3] column-major - { - final Frustum.Plane p = frustum.getPlanes()[Frustum.BOTTOM]; - final Vec3f p_n = p.n; - p_n.set( m30 + m10, - m31 + m11, - m32 + m12 ); - p.d = m33 + m13; - } - - // 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 Frustum.Plane p = frustum.getPlanes()[Frustum.TOP]; - final Vec3f p_n = p.n; - p_n.set( m30 - m10, - m31 - m11, - m32 - m12 ); - p.d = m33 - m13; - } - - // Near: a = m41m31, b = m42m32, c = m43m33, d = m44m34 - [1..4] column-major - // Near: a = m30m20, b = m31m21, c = m32m22, d = m33m23 - [0..3] column-major - { - final Frustum.Plane p = frustum.getPlanes()[Frustum.NEAR]; - final Vec3f p_n = p.n; - p_n.set( m30 + m20, - m31 + m21, - m32 + m22 ); - p.d = m33 + m23; - } - - // 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 = m32m22, d = m33m23 - [0..3] column-major - { - final Frustum.Plane p = frustum.getPlanes()[Frustum.FAR]; - final Vec3f p_n = p.n; - p_n.set( m30 - m20, - m31 - m21, - m32 - m22 ); - p.d = m33 - m23; - } - - // Normalize all planes - for (int i = 0; i < 6; ++i) { - final Plane p = frustum.getPlanes()[i]; - final Vec3f p_n = p.n; - final float invLen = 1f / p_n.length(); - p_n.scale(invLen); - p.d *= invLen; - } - } - - /** - * Set this matrix to the look-at matrix based on given parameters. - *- * Consist out of two matrix multiplications: - *
- * R = L x T, - * with L for look-at matrix and - * T for eye translation. - * - * Result R can be utilized for projection or modelview multiplication, i.e. - * M = M x R, - * with M being the projection or modelview matrix. - *- * - * @param eye 3 component eye vector - * @param center 3 component center vector - * @param up 3 component up vector - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public Matrix4f setToLookAt(final Vec3f eye, final Vec3f center, final Vec3f up, final Matrix4f tmp) { - // normalized forward! - final Vec3f fwd = new Vec3f( center.x() - eye.x(), - center.y() - eye.y(), - center.z() - eye.z() ).normalize(); - - /* Side = forward x up, normalized */ - final Vec3f side = fwd.cross(up).normalize(); - - /* Recompute up as: up = side x forward */ - final Vec3f up2 = side.cross(fwd); - - m00 = side.x(); - m10 = up2.x(); - m20 = -fwd.x(); - m30 = 0; - - m01 = side.y(); - m11 = up2.y(); - m21 = -fwd.y(); - m31 = 0; - - m02 = side.z(); - m12 = up2.z(); - m22 = -fwd.z(); - m32 = 0; - - m03 = 0; - m13 = 0; - m23 = 0; - m33 = 1; - - return mul( tmp.setToTranslation( -eye.x(), -eye.y(), -eye.z() ) ); - } - - /** - * Set this matrix to the pick matrix based on given parameters. - *
- * Traditional gluPickMatrix
implementation.
- *
- * Consist out of two matrix multiplications: - *
- * R = T x S, - * with T for viewport translation matrix and - * S for viewport scale matrix. - * - * Result R can be utilized for projection multiplication, i.e. - * P = P x R, - * with P being the projection matrix. - *- * - *
- * 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. - *
- * @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..() - // - - /** - * Rotate this matrix about give axis and angle in radians, i.e. multiply by {@link #setToRotationAxis(float, float, float, float) axis-rotation matrix}. - * @see Matrix-FAQ Q38 - * @param angrad angle in radians - * @param x x of rotation axis - * @param y y of rotation axis - * @param z z of rotation axis - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f rotate(final float ang_rad, final float x, final float y, final float z, final Matrix4f tmp) { - return mul( tmp.setToRotationAxis(ang_rad, x, y, z) ); - } - - /** - * Rotate this matrix about give axis and angle in radians, i.e. multiply by {@link #setToRotationAxis(float, Vec3f) axis-rotation matrix}. - * @see Matrix-FAQ Q38 - * @param angrad angle in radians - * @param axis rotation axis - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f rotate(final float ang_rad, final Vec3f axis, final Matrix4f tmp) { - return mul( tmp.setToRotationAxis(ang_rad, axis) ); - } - - /** - * Rotate this matrix with the given {@link Quaternion}, i.e. multiply by {@link #setToRotation(Quaternion) Quaternion's rotation matrix}. - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f rotate(final Quaternion quat, final Matrix4f tmp) { - return mul( tmp.setToRotation(quat) ); - } - - /** - * Translate this matrix, i.e. multiply by {@link #setToTranslation(float, float, float) translation matrix}. - * @param x x translation - * @param y y translation - * @param z z translation - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f translate(final float x, final float y, final float z, final Matrix4f tmp) { - return mul( tmp.setToTranslation(x, y, z) ); - } - - /** - * Translate this matrix, i.e. multiply by {@link #setToTranslation(Vec3f) translation matrix}. - * @param t translation Vec3f - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f translate(final Vec3f t, final Matrix4f tmp) { - return mul( tmp.setToTranslation(t) ); - } - - /** - * Scale this matrix, i.e. multiply by {@link #setToScale(float, float, float) scale matrix}. - * @param x x scale - * @param y y scale - * @param z z scale - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f scale(final float x, final float y, final float z, final Matrix4f tmp) { - return mul( tmp.setToScale(x, y, z) ); - } - - /** - * Scale this matrix, i.e. multiply by {@link #setToScale(float, float, float) scale matrix}. - * @param s scale for x-, y- and z-axis - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f scale(final float s, final Matrix4f tmp) { - return mul( tmp.setToScale(s, s, s) ); - } - - // - // Matrix Stack - // - - /** - * Push the matrix to it's stack, while preserving this matrix values. - * @see #pop() - */ - public final void push() { - stack.push(this); - } - - /** - * Pop the current matrix from it's stack, replacing this matrix values. - * @see #push() - */ - public final void pop() { - stack.pop(this); - } - - // - // equals - // - - /** - * Equals check using a given {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}. - *- * Implementation considers following corner cases: - *
- * Implementation considers following corner cases: - *
- * Traditional gluProject
implementation.
- *
- * Traditional gluProject
implementation.
- *
- * Traditional gluUnProject
implementation.
- *
- * Traditional gluUnProject
implementation.
- *
- * Traditional gluUnProject
implementation.
- *
- * Traditional gluUnProject4
implementation.
- *
- * Traditional gluUnProject4
implementation.
- *
- * Notes for picking winz0 and winz1: - *
- * Notes for picking winz0 and winz1: - *
0
- * in which case an {@link IndexOutOfBoundsException} is thrown.
- */
- public Stack(final int initialSize, final int growSize) {
- this.position = 0;
- this.growSize = growSize;
- this.buffer = new float[initialSize];
- }
-
- private final void growIfNecessary(final int length) throws IndexOutOfBoundsException {
- if( position + length > buffer.length ) {
- if( 0 >= growSize ) {
- throw new IndexOutOfBoundsException("Out of fixed stack size: "+this);
- }
- final float[] newBuffer =
- new float[buffer.length + growSize];
- System.arraycopy(buffer, 0, newBuffer, 0, position);
- buffer = newBuffer;
- }
- }
-
- public final Matrix4f push(final Matrix4f src) throws IndexOutOfBoundsException {
- growIfNecessary(16);
- src.get(buffer, position);
- position += 16;
- return src;
- }
-
- public final Matrix4f pop(final Matrix4f dest) throws IndexOutOfBoundsException {
- position -= 16;
- dest.load(buffer, position);
- return dest;
- }
- }
-}
--
cgit v1.2.3