Loading core/jni/android/opengl/util.cpp +87 −0 Original line number Diff line number Diff line Loading @@ -541,6 +541,87 @@ jint util_visibilityTest(JNIEnv *env, jclass clazz, indices.mData, indexCount); } #define I(_i, _j) ((_j)+ 4*(_i)) static void multiplyMM(float* r, const float* lhs, const float* rhs) { for (int i=0 ; i<4 ; i++) { const float rhs_i0 = rhs[ I(i,0) ]; float ri0 = lhs[ I(0,0) ] * rhs_i0; float ri1 = lhs[ I(0,1) ] * rhs_i0; float ri2 = lhs[ I(0,2) ] * rhs_i0; float ri3 = lhs[ I(0,3) ] * rhs_i0; for (int j=1 ; j<4 ; j++) { const float rhs_ij = rhs[ I(i,j) ]; ri0 += lhs[ I(j,0) ] * rhs_ij; ri1 += lhs[ I(j,1) ] * rhs_ij; ri2 += lhs[ I(j,2) ] * rhs_ij; ri3 += lhs[ I(j,3) ] * rhs_ij; } r[ I(i,0) ] = ri0; r[ I(i,1) ] = ri1; r[ I(i,2) ] = ri2; r[ I(i,3) ] = ri3; } } static void util_multiplyMM(JNIEnv *env, jclass clazz, jfloatArray result_ref, jint resultOffset, jfloatArray lhs_ref, jint lhsOffset, jfloatArray rhs_ref, jint rhsOffset) { FloatArrayHelper resultMat(env, result_ref, resultOffset, 16); FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16); FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 16); bool checkOK = resultMat.check() && lhs.check() && rhs.check(); if ( !checkOK ) { return; } resultMat.bind(); lhs.bind(); rhs.bind(); multiplyMM(resultMat.mData, lhs.mData, rhs.mData); resultMat.commitChanges(); } static void multiplyMV(float* r, const float* lhs, const float* rhs) { mx4transform(rhs[0], rhs[1], rhs[2], rhs[3], lhs, r); } static void util_multiplyMV(JNIEnv *env, jclass clazz, jfloatArray result_ref, jint resultOffset, jfloatArray lhs_ref, jint lhsOffset, jfloatArray rhs_ref, jint rhsOffset) { FloatArrayHelper resultV(env, result_ref, resultOffset, 4); FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16); FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 4); bool checkOK = resultV.check() && lhs.check() && rhs.check(); if ( !checkOK ) { return; } resultV.bind(); lhs.bind(); rhs.bind(); multiplyMV(resultV.mData, lhs.mData, rhs.mData); resultV.commitChanges(); } // --------------------------------------------------------------------------- // The internal format is no longer the same as pixel format, per Table 2 in Loading Loading @@ -928,6 +1009,11 @@ static jint etc1_getHeight(JNIEnv *env, jclass clazz, * JNI registration */ static const JNINativeMethod gMatrixMethods[] = { { "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM }, { "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV }, }; static const JNINativeMethod gVisibilityMethods[] = { { "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere }, { "frustumCullSpheres", "([FI[FII[III)I", (void*)util_frustumCullSpheres }, Loading Loading @@ -960,6 +1046,7 @@ typedef struct _ClassRegistrationInfo { } ClassRegistrationInfo; static const ClassRegistrationInfo gClasses[] = { {"android/opengl/Matrix", gMatrixMethods, NELEM(gMatrixMethods)}, {"android/opengl/Visibility", gVisibilityMethods, NELEM(gVisibilityMethods)}, {"android/opengl/GLUtils", gUtilsMethods, NELEM(gUtilsMethods)}, {"android/opengl/ETC1", gEtc1Methods, NELEM(gEtc1Methods)}, Loading opengl/java/android/opengl/Matrix.java +26 −193 Original line number Diff line number Diff line Loading @@ -40,11 +40,7 @@ import androidx.annotation.NonNull; public class Matrix { /** Temporary memory for operations that need temporary matrix data. */ private static final ThreadLocal<float[]> ThreadTmp = new ThreadLocal() { @Override protected float[] initialValue() { return new float[32]; } }; private final static float[] sTemp = new float[32]; /** * @deprecated All methods are static, do not instantiate this class. Loading @@ -52,40 +48,6 @@ public class Matrix { @Deprecated public Matrix() {} private static boolean overlap( float[] a, int aStart, int aLength, float[] b, int bStart, int bLength) { if (a != b) { return false; } if (aStart == bStart) { return true; } int aEnd = aStart + aLength; int bEnd = bStart + bLength; if (aEnd == bEnd) { return true; } if (aStart < bStart && bStart < aEnd) { return true; } if (aStart < bEnd && bEnd < aEnd) { return true; } if (bStart < aStart && aStart < bEnd) { return true; } if (bStart < aEnd && aEnd < bEnd) { return true; } return false; } /** * Multiplies two 4x4 matrices together and stores the result in a third 4x4 * matrix. In matrix notation: result = lhs x rhs. Due to the way Loading @@ -93,9 +55,9 @@ public class Matrix { * effect as first multiplying by the rhs matrix, then multiplying by * the lhs matrix. This is the opposite of what you might expect. * <p> * The same float array may be passed for result, lhs, and/or rhs. This * operation is expected to do the correct thing if the result elements * overlap with either of the lhs or rhs elements. * The same float array may be passed for result, lhs, and/or rhs. However, * the result element values are undefined if the result elements overlap * either the lhs or rhs elements. * * @param result The float array that holds the result. * @param resultOffset The offset into the result array where the result is Loading @@ -105,101 +67,20 @@ public class Matrix { * @param rhs The float array that holds the right-hand-side matrix. * @param rhsOffset The offset into the rhs array where the rhs is stored. * * @throws IllegalArgumentException under any of the following conditions: * result, lhs, or rhs are null; * resultOffset + 16 > result.length * or lhsOffset + 16 > lhs.length * or rhsOffset + 16 > rhs.length; * resultOffset < 0 or lhsOffset < 0 or rhsOffset < 0 * @throws IllegalArgumentException if result, lhs, or rhs are null, or if * resultOffset + 16 > result.length or lhsOffset + 16 > lhs.length or * rhsOffset + 16 > rhs.length. */ public static void multiplyMM(float[] result, int resultOffset, float[] lhs, int lhsOffset, float[] rhs, int rhsOffset) { // error checking if (result == null) { throw new IllegalArgumentException("result == null"); } if (lhs == null) { throw new IllegalArgumentException("lhs == null"); } if (rhs == null) { throw new IllegalArgumentException("rhs == null"); } if (resultOffset < 0) { throw new IllegalArgumentException("resultOffset < 0"); } if (lhsOffset < 0) { throw new IllegalArgumentException("lhsOffset < 0"); } if (rhsOffset < 0) { throw new IllegalArgumentException("rhsOffset < 0"); } if (result.length < resultOffset + 16) { throw new IllegalArgumentException("result.length < resultOffset + 16"); } if (lhs.length < lhsOffset + 16) { throw new IllegalArgumentException("lhs.length < lhsOffset + 16"); } if (rhs.length < rhsOffset + 16) { throw new IllegalArgumentException("rhs.length < rhsOffset + 16"); } // Check for overlap between rhs and result or lhs and result if ( overlap(result, resultOffset, 16, lhs, lhsOffset, 16) || overlap(result, resultOffset, 16, rhs, rhsOffset, 16) ) { float[] tmp = ThreadTmp.get(); for (int i=0; i<4; i++) { final float rhs_i0 = rhs[ 4*i + 0 + rhsOffset ]; float ri0 = lhs[ 0 + lhsOffset ] * rhs_i0; float ri1 = lhs[ 1 + lhsOffset ] * rhs_i0; float ri2 = lhs[ 2 + lhsOffset ] * rhs_i0; float ri3 = lhs[ 3 + 16 ] * rhs_i0; for (int j=1; j<4; j++) { final float rhs_ij = rhs[ 4*i + j + rhsOffset]; ri0 += lhs[ 4*j + 0 + lhsOffset ] * rhs_ij; ri1 += lhs[ 4*j + 1 + lhsOffset ] * rhs_ij; ri2 += lhs[ 4*j + 2 + lhsOffset ] * rhs_ij; ri3 += lhs[ 4*j + 3 + lhsOffset ] * rhs_ij; } tmp[ 4*i + 0 ] = ri0; tmp[ 4*i + 1 ] = ri1; tmp[ 4*i + 2 ] = ri2; tmp[ 4*i + 3 ] = ri3; } // copy from tmp to result for (int i=0; i < 16; i++) { result[ i + resultOffset ] = tmp[ i ]; } } else { for (int i=0; i<4; i++) { final float rhs_i0 = rhs[ 4*i + 0 + rhsOffset ]; float ri0 = lhs[ 0 + lhsOffset ] * rhs_i0; float ri1 = lhs[ 1 + lhsOffset ] * rhs_i0; float ri2 = lhs[ 2 + lhsOffset ] * rhs_i0; float ri3 = lhs[ 3 + lhsOffset ] * rhs_i0; for (int j=1; j<4; j++) { final float rhs_ij = rhs[ 4*i + j + rhsOffset]; ri0 += lhs[ 4*j + 0 + lhsOffset ] * rhs_ij; ri1 += lhs[ 4*j + 1 + lhsOffset ] * rhs_ij; ri2 += lhs[ 4*j + 2 + lhsOffset ] * rhs_ij; ri3 += lhs[ 4*j + 3 + lhsOffset ] * rhs_ij; } result[ 4*i + 0 + resultOffset ] = ri0; result[ 4*i + 1 + resultOffset ] = ri1; result[ 4*i + 2 + resultOffset ] = ri2; result[ 4*i + 3 + resultOffset ] = ri3; } } } public static native void multiplyMM(float[] result, int resultOffset, float[] lhs, int lhsOffset, float[] rhs, int rhsOffset); /** * Multiplies a 4 element vector by a 4x4 matrix and stores the result in a * 4-element column vector. In matrix notation: result = lhs x rhs * <p> * The same float array may be passed for resultVec, lhsMat, and/or rhsVec. * This operation is expected to do the correct thing if the result elements * overlap with either of the lhs or rhs elements. * However, the resultVec element values are undefined if the resultVec * elements overlap either the lhsMat or rhsVec elements. * * @param resultVec The float array that holds the result vector. * @param resultVecOffset The offset into the result array where the result Loading @@ -210,67 +91,14 @@ public class Matrix { * @param rhsVecOffset The offset into the rhs vector where the rhs vector * is stored. * * @throws IllegalArgumentException under any of the following conditions: * resultVec, lhsMat, or rhsVec are null; * resultVecOffset + 4 > resultVec.length * or lhsMatOffset + 16 > lhsMat.length * or rhsVecOffset + 4 > rhsVec.length; * resultVecOffset < 0 or lhsMatOffset < 0 or rhsVecOffset < 0 * @throws IllegalArgumentException if resultVec, lhsMat, * or rhsVec are null, or if resultVecOffset + 4 > resultVec.length * or lhsMatOffset + 16 > lhsMat.length or * rhsVecOffset + 4 > rhsVec.length. */ public static void multiplyMV(float[] resultVec, public static native void multiplyMV(float[] resultVec, int resultVecOffset, float[] lhsMat, int lhsMatOffset, float[] rhsVec, int rhsVecOffset) { // error checking if (resultVec == null) { throw new IllegalArgumentException("resultVec == null"); } if (lhsMat == null) { throw new IllegalArgumentException("lhsMat == null"); } if (rhsVec == null) { throw new IllegalArgumentException("rhsVec == null"); } if (resultVecOffset < 0) { throw new IllegalArgumentException("resultVecOffset < 0"); } if (lhsMatOffset < 0) { throw new IllegalArgumentException("lhsMatOffset < 0"); } if (rhsVecOffset < 0) { throw new IllegalArgumentException("rhsVecOffset < 0"); } if (resultVec.length < resultVecOffset + 4) { throw new IllegalArgumentException("resultVec.length < resultVecOffset + 4"); } if (lhsMat.length < lhsMatOffset + 16) { throw new IllegalArgumentException("lhsMat.length < lhsMatOffset + 16"); } if (rhsVec.length < rhsVecOffset + 4) { throw new IllegalArgumentException("rhsVec.length < rhsVecOffset + 4"); } float tmp0 = lhsMat[0 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + lhsMat[0 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + lhsMat[0 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + lhsMat[0 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; float tmp1 = lhsMat[1 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + lhsMat[1 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + lhsMat[1 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + lhsMat[1 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; float tmp2 = lhsMat[2 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + lhsMat[2 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + lhsMat[2 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + lhsMat[2 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; float tmp3 = lhsMat[3 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + lhsMat[3 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + lhsMat[3 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + lhsMat[3 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; resultVec[ 0 + resultVecOffset ] = tmp0; resultVec[ 1 + resultVecOffset ] = tmp1; resultVec[ 2 + resultVecOffset ] = tmp2; resultVec[ 3 + resultVecOffset ] = tmp3; } float[] rhsVec, int rhsVecOffset); /** * Transposes a 4 x 4 matrix. Loading Loading @@ -711,9 +539,10 @@ public class Matrix { public static void rotateM(float[] rm, int rmOffset, float[] m, int mOffset, float a, float x, float y, float z) { float[] tmp = ThreadTmp.get(); setRotateM(tmp, 16, a, x, y, z); multiplyMM(rm, rmOffset, m, mOffset, tmp, 16); synchronized(sTemp) { setRotateM(sTemp, 0, a, x, y, z); multiplyMM(rm, rmOffset, m, mOffset, sTemp, 0); } } /** Loading @@ -729,7 +558,11 @@ public class Matrix { */ public static void rotateM(float[] m, int mOffset, float a, float x, float y, float z) { rotateM(m, mOffset, m, mOffset, a, x, y, z); synchronized(sTemp) { setRotateM(sTemp, 0, a, x, y, z); multiplyMM(sTemp, 16, m, mOffset, sTemp, 0); System.arraycopy(sTemp, 16, m, mOffset, 16); } } /** Loading Loading
core/jni/android/opengl/util.cpp +87 −0 Original line number Diff line number Diff line Loading @@ -541,6 +541,87 @@ jint util_visibilityTest(JNIEnv *env, jclass clazz, indices.mData, indexCount); } #define I(_i, _j) ((_j)+ 4*(_i)) static void multiplyMM(float* r, const float* lhs, const float* rhs) { for (int i=0 ; i<4 ; i++) { const float rhs_i0 = rhs[ I(i,0) ]; float ri0 = lhs[ I(0,0) ] * rhs_i0; float ri1 = lhs[ I(0,1) ] * rhs_i0; float ri2 = lhs[ I(0,2) ] * rhs_i0; float ri3 = lhs[ I(0,3) ] * rhs_i0; for (int j=1 ; j<4 ; j++) { const float rhs_ij = rhs[ I(i,j) ]; ri0 += lhs[ I(j,0) ] * rhs_ij; ri1 += lhs[ I(j,1) ] * rhs_ij; ri2 += lhs[ I(j,2) ] * rhs_ij; ri3 += lhs[ I(j,3) ] * rhs_ij; } r[ I(i,0) ] = ri0; r[ I(i,1) ] = ri1; r[ I(i,2) ] = ri2; r[ I(i,3) ] = ri3; } } static void util_multiplyMM(JNIEnv *env, jclass clazz, jfloatArray result_ref, jint resultOffset, jfloatArray lhs_ref, jint lhsOffset, jfloatArray rhs_ref, jint rhsOffset) { FloatArrayHelper resultMat(env, result_ref, resultOffset, 16); FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16); FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 16); bool checkOK = resultMat.check() && lhs.check() && rhs.check(); if ( !checkOK ) { return; } resultMat.bind(); lhs.bind(); rhs.bind(); multiplyMM(resultMat.mData, lhs.mData, rhs.mData); resultMat.commitChanges(); } static void multiplyMV(float* r, const float* lhs, const float* rhs) { mx4transform(rhs[0], rhs[1], rhs[2], rhs[3], lhs, r); } static void util_multiplyMV(JNIEnv *env, jclass clazz, jfloatArray result_ref, jint resultOffset, jfloatArray lhs_ref, jint lhsOffset, jfloatArray rhs_ref, jint rhsOffset) { FloatArrayHelper resultV(env, result_ref, resultOffset, 4); FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16); FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 4); bool checkOK = resultV.check() && lhs.check() && rhs.check(); if ( !checkOK ) { return; } resultV.bind(); lhs.bind(); rhs.bind(); multiplyMV(resultV.mData, lhs.mData, rhs.mData); resultV.commitChanges(); } // --------------------------------------------------------------------------- // The internal format is no longer the same as pixel format, per Table 2 in Loading Loading @@ -928,6 +1009,11 @@ static jint etc1_getHeight(JNIEnv *env, jclass clazz, * JNI registration */ static const JNINativeMethod gMatrixMethods[] = { { "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM }, { "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV }, }; static const JNINativeMethod gVisibilityMethods[] = { { "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere }, { "frustumCullSpheres", "([FI[FII[III)I", (void*)util_frustumCullSpheres }, Loading Loading @@ -960,6 +1046,7 @@ typedef struct _ClassRegistrationInfo { } ClassRegistrationInfo; static const ClassRegistrationInfo gClasses[] = { {"android/opengl/Matrix", gMatrixMethods, NELEM(gMatrixMethods)}, {"android/opengl/Visibility", gVisibilityMethods, NELEM(gVisibilityMethods)}, {"android/opengl/GLUtils", gUtilsMethods, NELEM(gUtilsMethods)}, {"android/opengl/ETC1", gEtc1Methods, NELEM(gEtc1Methods)}, Loading
opengl/java/android/opengl/Matrix.java +26 −193 Original line number Diff line number Diff line Loading @@ -40,11 +40,7 @@ import androidx.annotation.NonNull; public class Matrix { /** Temporary memory for operations that need temporary matrix data. */ private static final ThreadLocal<float[]> ThreadTmp = new ThreadLocal() { @Override protected float[] initialValue() { return new float[32]; } }; private final static float[] sTemp = new float[32]; /** * @deprecated All methods are static, do not instantiate this class. Loading @@ -52,40 +48,6 @@ public class Matrix { @Deprecated public Matrix() {} private static boolean overlap( float[] a, int aStart, int aLength, float[] b, int bStart, int bLength) { if (a != b) { return false; } if (aStart == bStart) { return true; } int aEnd = aStart + aLength; int bEnd = bStart + bLength; if (aEnd == bEnd) { return true; } if (aStart < bStart && bStart < aEnd) { return true; } if (aStart < bEnd && bEnd < aEnd) { return true; } if (bStart < aStart && aStart < bEnd) { return true; } if (bStart < aEnd && aEnd < bEnd) { return true; } return false; } /** * Multiplies two 4x4 matrices together and stores the result in a third 4x4 * matrix. In matrix notation: result = lhs x rhs. Due to the way Loading @@ -93,9 +55,9 @@ public class Matrix { * effect as first multiplying by the rhs matrix, then multiplying by * the lhs matrix. This is the opposite of what you might expect. * <p> * The same float array may be passed for result, lhs, and/or rhs. This * operation is expected to do the correct thing if the result elements * overlap with either of the lhs or rhs elements. * The same float array may be passed for result, lhs, and/or rhs. However, * the result element values are undefined if the result elements overlap * either the lhs or rhs elements. * * @param result The float array that holds the result. * @param resultOffset The offset into the result array where the result is Loading @@ -105,101 +67,20 @@ public class Matrix { * @param rhs The float array that holds the right-hand-side matrix. * @param rhsOffset The offset into the rhs array where the rhs is stored. * * @throws IllegalArgumentException under any of the following conditions: * result, lhs, or rhs are null; * resultOffset + 16 > result.length * or lhsOffset + 16 > lhs.length * or rhsOffset + 16 > rhs.length; * resultOffset < 0 or lhsOffset < 0 or rhsOffset < 0 * @throws IllegalArgumentException if result, lhs, or rhs are null, or if * resultOffset + 16 > result.length or lhsOffset + 16 > lhs.length or * rhsOffset + 16 > rhs.length. */ public static void multiplyMM(float[] result, int resultOffset, float[] lhs, int lhsOffset, float[] rhs, int rhsOffset) { // error checking if (result == null) { throw new IllegalArgumentException("result == null"); } if (lhs == null) { throw new IllegalArgumentException("lhs == null"); } if (rhs == null) { throw new IllegalArgumentException("rhs == null"); } if (resultOffset < 0) { throw new IllegalArgumentException("resultOffset < 0"); } if (lhsOffset < 0) { throw new IllegalArgumentException("lhsOffset < 0"); } if (rhsOffset < 0) { throw new IllegalArgumentException("rhsOffset < 0"); } if (result.length < resultOffset + 16) { throw new IllegalArgumentException("result.length < resultOffset + 16"); } if (lhs.length < lhsOffset + 16) { throw new IllegalArgumentException("lhs.length < lhsOffset + 16"); } if (rhs.length < rhsOffset + 16) { throw new IllegalArgumentException("rhs.length < rhsOffset + 16"); } // Check for overlap between rhs and result or lhs and result if ( overlap(result, resultOffset, 16, lhs, lhsOffset, 16) || overlap(result, resultOffset, 16, rhs, rhsOffset, 16) ) { float[] tmp = ThreadTmp.get(); for (int i=0; i<4; i++) { final float rhs_i0 = rhs[ 4*i + 0 + rhsOffset ]; float ri0 = lhs[ 0 + lhsOffset ] * rhs_i0; float ri1 = lhs[ 1 + lhsOffset ] * rhs_i0; float ri2 = lhs[ 2 + lhsOffset ] * rhs_i0; float ri3 = lhs[ 3 + 16 ] * rhs_i0; for (int j=1; j<4; j++) { final float rhs_ij = rhs[ 4*i + j + rhsOffset]; ri0 += lhs[ 4*j + 0 + lhsOffset ] * rhs_ij; ri1 += lhs[ 4*j + 1 + lhsOffset ] * rhs_ij; ri2 += lhs[ 4*j + 2 + lhsOffset ] * rhs_ij; ri3 += lhs[ 4*j + 3 + lhsOffset ] * rhs_ij; } tmp[ 4*i + 0 ] = ri0; tmp[ 4*i + 1 ] = ri1; tmp[ 4*i + 2 ] = ri2; tmp[ 4*i + 3 ] = ri3; } // copy from tmp to result for (int i=0; i < 16; i++) { result[ i + resultOffset ] = tmp[ i ]; } } else { for (int i=0; i<4; i++) { final float rhs_i0 = rhs[ 4*i + 0 + rhsOffset ]; float ri0 = lhs[ 0 + lhsOffset ] * rhs_i0; float ri1 = lhs[ 1 + lhsOffset ] * rhs_i0; float ri2 = lhs[ 2 + lhsOffset ] * rhs_i0; float ri3 = lhs[ 3 + lhsOffset ] * rhs_i0; for (int j=1; j<4; j++) { final float rhs_ij = rhs[ 4*i + j + rhsOffset]; ri0 += lhs[ 4*j + 0 + lhsOffset ] * rhs_ij; ri1 += lhs[ 4*j + 1 + lhsOffset ] * rhs_ij; ri2 += lhs[ 4*j + 2 + lhsOffset ] * rhs_ij; ri3 += lhs[ 4*j + 3 + lhsOffset ] * rhs_ij; } result[ 4*i + 0 + resultOffset ] = ri0; result[ 4*i + 1 + resultOffset ] = ri1; result[ 4*i + 2 + resultOffset ] = ri2; result[ 4*i + 3 + resultOffset ] = ri3; } } } public static native void multiplyMM(float[] result, int resultOffset, float[] lhs, int lhsOffset, float[] rhs, int rhsOffset); /** * Multiplies a 4 element vector by a 4x4 matrix and stores the result in a * 4-element column vector. In matrix notation: result = lhs x rhs * <p> * The same float array may be passed for resultVec, lhsMat, and/or rhsVec. * This operation is expected to do the correct thing if the result elements * overlap with either of the lhs or rhs elements. * However, the resultVec element values are undefined if the resultVec * elements overlap either the lhsMat or rhsVec elements. * * @param resultVec The float array that holds the result vector. * @param resultVecOffset The offset into the result array where the result Loading @@ -210,67 +91,14 @@ public class Matrix { * @param rhsVecOffset The offset into the rhs vector where the rhs vector * is stored. * * @throws IllegalArgumentException under any of the following conditions: * resultVec, lhsMat, or rhsVec are null; * resultVecOffset + 4 > resultVec.length * or lhsMatOffset + 16 > lhsMat.length * or rhsVecOffset + 4 > rhsVec.length; * resultVecOffset < 0 or lhsMatOffset < 0 or rhsVecOffset < 0 * @throws IllegalArgumentException if resultVec, lhsMat, * or rhsVec are null, or if resultVecOffset + 4 > resultVec.length * or lhsMatOffset + 16 > lhsMat.length or * rhsVecOffset + 4 > rhsVec.length. */ public static void multiplyMV(float[] resultVec, public static native void multiplyMV(float[] resultVec, int resultVecOffset, float[] lhsMat, int lhsMatOffset, float[] rhsVec, int rhsVecOffset) { // error checking if (resultVec == null) { throw new IllegalArgumentException("resultVec == null"); } if (lhsMat == null) { throw new IllegalArgumentException("lhsMat == null"); } if (rhsVec == null) { throw new IllegalArgumentException("rhsVec == null"); } if (resultVecOffset < 0) { throw new IllegalArgumentException("resultVecOffset < 0"); } if (lhsMatOffset < 0) { throw new IllegalArgumentException("lhsMatOffset < 0"); } if (rhsVecOffset < 0) { throw new IllegalArgumentException("rhsVecOffset < 0"); } if (resultVec.length < resultVecOffset + 4) { throw new IllegalArgumentException("resultVec.length < resultVecOffset + 4"); } if (lhsMat.length < lhsMatOffset + 16) { throw new IllegalArgumentException("lhsMat.length < lhsMatOffset + 16"); } if (rhsVec.length < rhsVecOffset + 4) { throw new IllegalArgumentException("rhsVec.length < rhsVecOffset + 4"); } float tmp0 = lhsMat[0 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + lhsMat[0 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + lhsMat[0 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + lhsMat[0 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; float tmp1 = lhsMat[1 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + lhsMat[1 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + lhsMat[1 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + lhsMat[1 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; float tmp2 = lhsMat[2 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + lhsMat[2 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + lhsMat[2 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + lhsMat[2 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; float tmp3 = lhsMat[3 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] + lhsMat[3 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] + lhsMat[3 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] + lhsMat[3 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset]; resultVec[ 0 + resultVecOffset ] = tmp0; resultVec[ 1 + resultVecOffset ] = tmp1; resultVec[ 2 + resultVecOffset ] = tmp2; resultVec[ 3 + resultVecOffset ] = tmp3; } float[] rhsVec, int rhsVecOffset); /** * Transposes a 4 x 4 matrix. Loading Loading @@ -711,9 +539,10 @@ public class Matrix { public static void rotateM(float[] rm, int rmOffset, float[] m, int mOffset, float a, float x, float y, float z) { float[] tmp = ThreadTmp.get(); setRotateM(tmp, 16, a, x, y, z); multiplyMM(rm, rmOffset, m, mOffset, tmp, 16); synchronized(sTemp) { setRotateM(sTemp, 0, a, x, y, z); multiplyMM(rm, rmOffset, m, mOffset, sTemp, 0); } } /** Loading @@ -729,7 +558,11 @@ public class Matrix { */ public static void rotateM(float[] m, int mOffset, float a, float x, float y, float z) { rotateM(m, mOffset, m, mOffset, a, x, y, z); synchronized(sTemp) { setRotateM(sTemp, 0, a, x, y, z); multiplyMM(sTemp, 16, m, mOffset, sTemp, 0); System.arraycopy(sTemp, 16, m, mOffset, 16); } } /** Loading