Matrix.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.opengl;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Matrix math utilities. These methods operate on OpenGL ES format
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * matrices and vectors stored in float arrays.
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Matrices are 4 x 4 column-vector matrices stored in column-major
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * order:
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  m[offset +  0] m[offset +  4] m[offset +  8] m[offset + 12]
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  m[offset +  1] m[offset +  5] m[offset +  9] m[offset + 13]
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  m[offset +  2] m[offset +  6] m[offset + 10] m[offset + 14]
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  m[offset +  3] m[offset +  7] m[offset + 11] m[offset + 15]
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre>
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Vectors are 4 row x 1 column column-vectors stored in order:
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * v[offset + 0]
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * v[offset + 1]
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * v[offset + 2]
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * v[offset + 3]
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre>
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Matrix {
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Multiply two 4x4 matrices together and store the result in a third 4x4
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * matrix. In matrix notation: result = lhs x rhs. Due to the way
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * matrix multiplication works, the result matrix will have the same
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * effect as first multiplying by the rhs matrix, then multiplying by
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the lhs matrix. This is the opposite of what you might expect.
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The same float array may be passed for result, lhs, and/or rhs. However,
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the result element values are undefined if the result elements overlap
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * either the lhs or rhs elements.
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param result The float array that holds the result.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resultOffset The offset into the result array where the result is
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        stored.
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param lhs The float array that holds the left-hand-side matrix.
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param lhsOffset The offset into the lhs array where the lhs is stored
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rhs The float array that holds the right-hand-side matrix.
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rhsOffset The offset into the rhs array where the rhs is stored.
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if result, lhs, or rhs are null, or if
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * resultOffset + 16 > result.length or lhsOffset + 16 > lhs.length or
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rhsOffset + 16 > rhs.length.
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static native void multiplyMM(float[] result, int resultOffset,
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] lhs, int lhsOffset, float[] rhs, int rhsOffset);
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Multiply a 4 element vector by a 4x4 matrix and store the result in a 4
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * element column vector. In matrix notation: result = lhs x rhs
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The same float array may be passed for resultVec, lhsMat, and/or rhsVec.
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * However, the resultVec element values are undefined if the resultVec
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * elements overlap either the lhsMat or rhsVec elements.
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resultVec The float array that holds the result vector.
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resultVecOffset The offset into the result array where the result
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        vector is stored.
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param lhsMat The float array that holds the left-hand-side matrix.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param lhsMatOffset The offset into the lhs array where the lhs is stored
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rhsVec The float array that holds the right-hand-side vector.
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rhsVecOffset The offset into the rhs vector where the rhs vector
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        is stored.
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if resultVec, lhsMat,
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or rhsVec are null, or if resultVecOffset + 4 > resultVec.length
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or lhsMatOffset + 16 > lhsMat.length or
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rhsVecOffset + 4 > rhsVec.length.
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static native void multiplyMV(float[] resultVec,
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int resultVecOffset, float[] lhsMat, int lhsMatOffset,
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] rhsVec, int rhsVecOffset);
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Transposes a 4 x 4 matrix.
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mTrans the array that holds the output inverted matrix
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mTransOffset an offset into mInv where the inverted matrix is
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        stored.
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m the input array
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset an offset into m where the matrix is stored.
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void transposeM(float[] mTrans, int mTransOffset, float[] m,
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mOffset) {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < 4; i++) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mBase = i * 4 + mOffset;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTrans[i + mTransOffset] = m[mBase];
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTrans[i + 4 + mTransOffset] = m[mBase + 1];
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTrans[i + 8 + mTransOffset] = m[mBase + 2];
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTrans[i + 12 + mTransOffset] = m[mBase + 3];
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inverts a 4 x 4 matrix.
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mInv the array that holds the output inverted matrix
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mInvOffset an offset into mInv where the inverted matrix is
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        stored.
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m the input array
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset an offset into m where the matrix is stored.
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the matrix could be inverted, false if it could not.
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean invertM(float[] mInv, int mInvOffset, float[] m,
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mOffset) {
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Invert a 4 x 4 matrix using Cramer's Rule
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // array of transpose source matrix
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float[] src = new float[16];
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // transpose matrix
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        transposeM(src, 0, m, mOffset);
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // temp array for pairs
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float[] tmp = new float[12];
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate pairs for first 8 elements (cofactors)
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[0] = src[10] * src[15];
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[1] = src[11] * src[14];
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[2] = src[9] * src[15];
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[3] = src[11] * src[13];
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[4] = src[9] * src[14];
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[5] = src[10] * src[13];
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[6] = src[8] * src[15];
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[7] = src[11] * src[12];
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[8] = src[8] * src[14];
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[9] = src[10] * src[12];
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[10] = src[8] * src[13];
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[11] = src[9] * src[12];
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Holds the destination matrix while we're building it up.
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float[] dst = new float[16];
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate first 8 elements (cofactors)
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7];
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7];
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7];
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[1] -= tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7];
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7];
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[2] -= tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7];
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6];
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[3] -= tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6];
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[4] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3];
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[4] -= tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3];
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[5] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3];
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[5] -= tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3];
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[6] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3];
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3];
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2];
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2];
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate pairs for second 8 elements (cofactors)
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[0] = src[2] * src[7];
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[1] = src[3] * src[6];
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[2] = src[1] * src[7];
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[3] = src[3] * src[5];
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[4] = src[1] * src[6];
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[5] = src[2] * src[5];
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[6] = src[0] * src[7];
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[7] = src[3] * src[4];
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[8] = src[0] * src[6];
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[9] = src[2] * src[4];
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[10] = src[0] * src[5];
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        tmp[11] = src[1] * src[4];
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate second 8 elements (cofactors)
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15];
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15];
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15];
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[9] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15];
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15];
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[10] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15];
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14];
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[11] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14];
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9];
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[12] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10];
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10];
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[13] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8];
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[14] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8];
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9];
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9];
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8];
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate determinant
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float det =
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3]
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        * dst[3];
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (det == 0.0f) {
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate matrix inverse
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        det = 1 / det;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int j = 0; j < 16; j++)
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInv[j + mInvOffset] = dst[j] * det;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes an orthographic projection matrix.
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m returns the result
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param left
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param right
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bottom
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param top
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param near
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param far
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void orthoM(float[] m, int mOffset,
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float left, float right, float bottom, float top,
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float near, float far) {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (left == right) {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("left == right");
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bottom == top) {
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("bottom == top");
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (near == far) {
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("near == far");
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_width  = 1.0f / (right - left);
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_height = 1.0f / (top - bottom);
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_depth  = 1.0f / (far - near);
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float x =  2.0f * (r_width);
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float y =  2.0f * (r_height);
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float z = -2.0f * (r_depth);
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float tx = -(right + left) * r_width;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float ty = -(top + bottom) * r_height;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float tz = -(far + near) * r_depth;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 0] = x;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 5] = y;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset +10] = z;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset +12] = tx;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset +13] = ty;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset +14] = tz;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset +15] = 1.0f;
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 1] = 0.0f;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 2] = 0.0f;
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 3] = 0.0f;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 4] = 0.0f;
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 6] = 0.0f;
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 7] = 0.0f;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 8] = 0.0f;
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 9] = 0.0f;
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 11] = 0.0f;
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Define a projection matrix in terms of six clip planes
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m the float array that holds the perspective matrix
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param offset the offset into float array m where the perspective
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * matrix data is written
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param left
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param right
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bottom
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param top
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param near
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param far
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void frustumM(float[] m, int offset,
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float left, float right, float bottom, float top,
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float near, float far) {
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (left == right) {
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("left == right");
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (top == bottom) {
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("top == bottom");
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (near == far) {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("near == far");
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (near <= 0.0f) {
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("near <= 0.0f");
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (far <= 0.0f) {
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("far <= 0.0f");
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_width  = 1.0f / (right - left);
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_height = 1.0f / (top - bottom);
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_depth  = 1.0f / (near - far);
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float x = 2.0f * (near * r_width);
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float y = 2.0f * (near * r_height);
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float A = 2.0f * ((right + left) * r_width);
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float B = (top + bottom) * r_height;
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float C = (far + near) * r_depth;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float D = 2.0f * (far * near * r_depth);
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 0] = x;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 5] = y;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 8] = A;
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  9] = B;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 10] = C;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 14] = D;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 11] = -1.0f;
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  1] = 0.0f;
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  2] = 0.0f;
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  3] = 0.0f;
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  4] = 0.0f;
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  6] = 0.0f;
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  7] = 0.0f;
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 12] = 0.0f;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 13] = 0.0f;
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 15] = 0.0f;
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes the length of a vector
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x x coordinate of a vector
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y y coordinate of a vector
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z z coordinate of a vector
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the length of a vector
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static float length(float x, float y, float z) {
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (float) Math.sqrt(x * x + y * y + z * z);
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets matrix m to the identity matrix.
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sm returns the result
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param smOffset index into sm where the result matrix starts
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void setIdentityM(float[] sm, int smOffset) {
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<16 ; i++) {
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[smOffset + i] = 0;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for(int i = 0; i < 16; i += 5) {
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[smOffset + i] = 1.0f;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Scales matrix  m by x, y, and z, putting the result in sm
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sm returns the result
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param smOffset index into sm where the result matrix starts
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m source matrix
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the source matrix starts
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x scale factor x
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y scale factor y
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z scale factor z
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void scaleM(float[] sm, int smOffset,
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] m, int mOffset,
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x, float y, float z) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int smi = smOffset + i;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mi = mOffset + i;
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[     smi] = m[     mi] * x;
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[ 4 + smi] = m[ 4 + mi] * y;
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[ 8 + smi] = m[ 8 + mi] * z;
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[12 + smi] = m[12 + mi];
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Scales matrix m in place by sx, sy, and sz
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m matrix to scale
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the matrix starts
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x scale factor x
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y scale factor y
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z scale factor z
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void scaleM(float[] m, int mOffset,
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x, float y, float z) {
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mi = mOffset + i;
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m[     mi] *= x;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m[ 4 + mi] *= y;
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m[ 8 + mi] *= z;
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Translates matrix m by x, y, and z, putting the result in tm
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param tm returns the result
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param tmOffset index into sm where the result matrix starts
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m source matrix
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the source matrix starts
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x translation factor x
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y translation factor y
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z translation factor z
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void translateM(float[] tm, int tmOffset,
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] m, int mOffset,
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x, float y, float z) {
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<12 ; i++) {
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tm[tmOffset + i] = m[mOffset + i];
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int tmi = tmOffset + i;
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mi = mOffset + i;
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tm[12 + tmi] = m[mi] * x + m[4 + mi] * y + m[8 + mi] * z +
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                m[12 + mi];
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Translates matrix m by x, y, and z in place.
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m matrix
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the matrix starts
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x translation factor x
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y translation factor y
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z translation factor z
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void translateM(
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] m, int mOffset,
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x, float y, float z) {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mi = mOffset + i;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m[12 + mi] += m[mi] * x + m[4 + mi] * y + m[8 + mi] * z;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rotates matrix m by angle a (in degrees) around the axis (x, y, z)
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rm returns the result
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rmOffset index into rm where the result matrix starts
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m source matrix
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the source matrix starts
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param a angle to rotate in degrees
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x scale factor x
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y scale factor y
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z scale factor z
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void rotateM(float[] rm, int rmOffset,
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] m, int mOffset,
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, float x, float y, float z) {
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float[] r = new float[16];
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setRotateM(r, 0, a, x, y, z);
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        multiplyMM(rm, rmOffset, m, mOffset, r, 0);
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rotates matrix m in place by angle a (in degrees)
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * around the axis (x, y, z)
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m source matrix
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the matrix starts
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param a angle to rotate in degrees
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x scale factor x
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y scale factor y
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z scale factor z
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void rotateM(float[] m, int mOffset,
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, float x, float y, float z) {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float[] temp = new float[32];
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setRotateM(temp, 0, a, x, y, z);
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        multiplyMM(temp, 16, m, mOffset, temp, 0);
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        System.arraycopy(temp, 16, m, mOffset, 16);
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rotates matrix m by angle a (in degrees) around the axis (x, y, z)
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rm returns the result
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rmOffset index into rm where the result matrix starts
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param a angle to rotate in degrees
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x scale factor x
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y scale factor y
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z scale factor z
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void setRotateM(float[] rm, int rmOffset,
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, float x, float y, float z) {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 3] = 0;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 7] = 0;
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 11]= 0;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 12]= 0;
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 13]= 0;
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 14]= 0;
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 15]= 1;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a *= (float) (Math.PI / 180.0f);
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float s = (float) Math.sin(a);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float c = (float) Math.cos(a);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (1.0f == x && 0.0f == y && 0.0f == z) {
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 5] = c;   rm[rmOffset + 10]= c;
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 6] = s;   rm[rmOffset + 9] = -s;
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 1] = 0;   rm[rmOffset + 2] = 0;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 4] = 0;   rm[rmOffset + 8] = 0;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 0] = 1;
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (0.0f == x && 1.0f == y && 0.0f == z) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 0] = c;   rm[rmOffset + 10]= c;
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 8] = s;   rm[rmOffset + 2] = -s;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 1] = 0;   rm[rmOffset + 4] = 0;
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 6] = 0;   rm[rmOffset + 9] = 0;
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 5] = 1;
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (0.0f == x && 0.0f == y && 1.0f == z) {
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 0] = c;   rm[rmOffset + 5] = c;
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 1] = s;   rm[rmOffset + 4] = -s;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 2] = 0;   rm[rmOffset + 6] = 0;
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 8] = 0;   rm[rmOffset + 9] = 0;
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 10]= 1;
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float len = length(x, y, z);
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (1.0f != len) {
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float recipLen = 1.0f / len;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                x *= recipLen;
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                y *= recipLen;
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                z *= recipLen;
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float nc = 1.0f - c;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float xy = x * y;
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float yz = y * z;
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float zx = z * x;
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float xs = x * s;
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float ys = y * s;
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float zs = z * s;
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  0] = x*x*nc +  c;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  4] =  xy*nc - zs;
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  8] =  zx*nc + ys;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  1] =  xy*nc + zs;
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  5] = y*y*nc +  c;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  9] =  yz*nc - xs;
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  2] =  zx*nc - ys;
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  6] =  yz*nc + xs;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 10] = z*z*nc +  c;
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Converts Euler angles to a rotation matrix
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rm returns the result
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rmOffset index into rm where the result matrix starts
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x angle of rotation, in degrees
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y angle of rotation, in degrees
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z angle of rotation, in degrees
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void setRotateEulerM(float[] rm, int rmOffset,
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x, float y, float z) {
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        x *= (float) (Math.PI / 180.0f);
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        y *= (float) (Math.PI / 180.0f);
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        z *= (float) (Math.PI / 180.0f);
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float cx = (float) Math.cos(x);
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float sx = (float) Math.sin(x);
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float cy = (float) Math.cos(y);
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float sy = (float) Math.sin(y);
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float cz = (float) Math.cos(z);
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float sz = (float) Math.sin(z);
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float cxsy = cx * sy;
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float sxsy = sx * sy;
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 0]  =   cy * cz;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 1]  =  -cy * sz;
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 2]  =   sy;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 3]  =  0.0f;
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 4]  =  cxsy * cz + cx * sz;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 5]  = -cxsy * sz + cx * cz;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 6]  =  -sx * cy;
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 7]  =  0.0f;
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 8]  = -sxsy * cz + sx * sz;
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 9]  =  sxsy * sz + sx * cz;
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 10] =  cx * cy;
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 11] =  0.0f;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 12] =  0.0f;
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 13] =  0.0f;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 14] =  0.0f;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 15] =  1.0f;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
586