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.
22043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden * <p>
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]
29043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden *  m[offset +  3] m[offset +  7] m[offset + 11] m[offset + 15]</pre>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
31043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden * Vectors are 4 x 1 column vectors stored in order:
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * v[offset + 0]
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * v[offset + 1]
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * v[offset + 2]
36043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden * v[offset + 3]</pre>
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Matrix {
39cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich
40cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich    /** Temporary memory for operations that need temporary matrix data. */
41cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich    private final static float[] sTemp = new float[32];
42cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
44043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @deprecated All methods are static, do not instantiate this class.
45043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     */
46043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden    @Deprecated
47043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden    public Matrix() {}
48043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden
49043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden    /**
50043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Multiplies two 4x4 matrices together and stores the result in a third 4x4
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * matrix. In matrix notation: result = lhs x rhs. Due to the way
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * matrix multiplication works, the result matrix will have the same
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * effect as first multiplying by the rhs matrix, then multiplying by
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the lhs matrix. This is the opposite of what you might expect.
55043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * <p>
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The same float array may be passed for result, lhs, and/or rhs. However,
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the result element values are undefined if the result elements overlap
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * either the lhs or rhs elements.
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param result The float array that holds the result.
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resultOffset The offset into the result array where the result is
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        stored.
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param lhs The float array that holds the left-hand-side matrix.
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param lhsOffset The offset into the lhs array where the lhs is stored
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rhs The float array that holds the right-hand-side matrix.
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rhsOffset The offset into the rhs array where the rhs is stored.
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if result, lhs, or rhs are null, or if
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * resultOffset + 16 > result.length or lhsOffset + 16 > lhs.length or
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rhsOffset + 16 > rhs.length.
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static native void multiplyMM(float[] result, int resultOffset,
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] lhs, int lhsOffset, float[] rhs, int rhsOffset);
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
76043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Multiplies a 4 element vector by a 4x4 matrix and stores the result in a
77043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * 4-element column vector. In matrix notation: result = lhs x rhs
78043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * <p>
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The same float array may be passed for resultVec, lhsMat, and/or rhsVec.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * However, the resultVec element values are undefined if the resultVec
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * elements overlap either the lhsMat or rhsVec elements.
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resultVec The float array that holds the result vector.
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resultVecOffset The offset into the result array where the result
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        vector is stored.
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param lhsMat The float array that holds the left-hand-side matrix.
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param lhsMatOffset The offset into the lhs array where the lhs is stored
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rhsVec The float array that holds the right-hand-side vector.
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rhsVecOffset The offset into the rhs vector where the rhs vector
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        is stored.
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if resultVec, lhsMat,
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or rhsVec are null, or if resultVecOffset + 4 > resultVec.length
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or lhsMatOffset + 16 > lhsMat.length or
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rhsVecOffset + 4 > rhsVec.length.
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static native void multiplyMV(float[] resultVec,
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int resultVecOffset, float[] lhsMat, int lhsMatOffset,
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] rhsVec, int rhsVecOffset);
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Transposes a 4 x 4 matrix.
103043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * <p>
104043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * mTrans and m must not overlap.
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
106043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param mTrans the array that holds the output transposed matrix
107043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param mTransOffset an offset into mTrans where the transposed matrix is
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        stored.
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m the input array
110043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param mOffset an offset into m where the input matrix is stored.
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void transposeM(float[] mTrans, int mTransOffset, float[] m,
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mOffset) {
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < 4; i++) {
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mBase = i * 4 + mOffset;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTrans[i + mTransOffset] = m[mBase];
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTrans[i + 4 + mTransOffset] = m[mBase + 1];
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTrans[i + 8 + mTransOffset] = m[mBase + 2];
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTrans[i + 12 + mTransOffset] = m[mBase + 3];
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inverts a 4 x 4 matrix.
125043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * <p>
126043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * mInv and m must not overlap.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mInv the array that holds the output inverted matrix
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mInvOffset an offset into mInv where the inverted matrix is
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        stored.
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m the input array
132043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param mOffset an offset into m where the input matrix is stored.
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the matrix could be inverted, false if it could not.
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean invertM(float[] mInv, int mInvOffset, float[] m,
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mOffset) {
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Invert a 4 x 4 matrix using Cramer's Rule
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // transpose matrix
140cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src0  = m[mOffset +  0];
141cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src4  = m[mOffset +  1];
142cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src8  = m[mOffset +  2];
143cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src12 = m[mOffset +  3];
144cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich
145cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src1  = m[mOffset +  4];
146cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src5  = m[mOffset +  5];
147cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src9  = m[mOffset +  6];
148cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src13 = m[mOffset +  7];
149cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich
150cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src2  = m[mOffset +  8];
151cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src6  = m[mOffset +  9];
152cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src10 = m[mOffset + 10];
153cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src14 = m[mOffset + 11];
154cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich
155cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src3  = m[mOffset + 12];
156cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src7  = m[mOffset + 13];
157cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src11 = m[mOffset + 14];
158cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float src15 = m[mOffset + 15];
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate pairs for first 8 elements (cofactors)
161cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp0  = src10 * src15;
162cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp1  = src11 * src14;
163cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp2  = src9  * src15;
164cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp3  = src11 * src13;
165cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp4  = src9  * src14;
166cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp5  = src10 * src13;
167cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp6  = src8  * src15;
168cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp7  = src11 * src12;
169cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp8  = src8  * src14;
170cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp9  = src10 * src12;
171cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp10 = src8  * src13;
172cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float atmp11 = src9  * src12;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate first 8 elements (cofactors)
175cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst0  = (atmp0 * src5 + atmp3 * src6 + atmp4  * src7)
176cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (atmp1 * src5 + atmp2 * src6 + atmp5  * src7);
177cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst1  = (atmp1 * src4 + atmp6 * src6 + atmp9  * src7)
178cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (atmp0 * src4 + atmp7 * src6 + atmp8  * src7);
179cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst2  = (atmp2 * src4 + atmp7 * src5 + atmp10 * src7)
180cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (atmp3 * src4 + atmp6 * src5 + atmp11 * src7);
181cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst3  = (atmp5 * src4 + atmp8 * src5 + atmp11 * src6)
182cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (atmp4 * src4 + atmp9 * src5 + atmp10 * src6);
183cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst4  = (atmp1 * src1 + atmp2 * src2 + atmp5  * src3)
184cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (atmp0 * src1 + atmp3 * src2 + atmp4  * src3);
185cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst5  = (atmp0 * src0 + atmp7 * src2 + atmp8  * src3)
186cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (atmp1 * src0 + atmp6 * src2 + atmp9  * src3);
187cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst6  = (atmp3 * src0 + atmp6 * src1 + atmp11 * src3)
188cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (atmp2 * src0 + atmp7 * src1 + atmp10 * src3);
189cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst7  = (atmp4 * src0 + atmp9 * src1 + atmp10 * src2)
190cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (atmp5 * src0 + atmp8 * src1 + atmp11 * src2);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate pairs for second 8 elements (cofactors)
193cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp0  = src2 * src7;
194cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp1  = src3 * src6;
195cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp2  = src1 * src7;
196cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp3  = src3 * src5;
197cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp4  = src1 * src6;
198cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp5  = src2 * src5;
199cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp6  = src0 * src7;
200cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp7  = src3 * src4;
201cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp8  = src0 * src6;
202cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp9  = src2 * src4;
203cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp10 = src0 * src5;
204cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float btmp11 = src1 * src4;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate second 8 elements (cofactors)
207cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst8  = (btmp0  * src13 + btmp3  * src14 + btmp4  * src15)
208cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (btmp1  * src13 + btmp2  * src14 + btmp5  * src15);
209cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst9  = (btmp1  * src12 + btmp6  * src14 + btmp9  * src15)
210cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (btmp0  * src12 + btmp7  * src14 + btmp8  * src15);
211cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst10 = (btmp2  * src12 + btmp7  * src13 + btmp10 * src15)
212cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (btmp3  * src12 + btmp6  * src13 + btmp11 * src15);
213cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst11 = (btmp5  * src12 + btmp8  * src13 + btmp11 * src14)
214cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (btmp4  * src12 + btmp9  * src13 + btmp10 * src14);
215cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst12 = (btmp2  * src10 + btmp5  * src11 + btmp1  * src9 )
216cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (btmp4  * src11 + btmp0  * src9  + btmp3  * src10);
217cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst13 = (btmp8  * src11 + btmp0  * src8  + btmp7  * src10)
218cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (btmp6  * src10 + btmp9  * src11 + btmp1  * src8 );
219cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst14 = (btmp6  * src9  + btmp11 * src11 + btmp3  * src8 )
220cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (btmp10 * src11 + btmp2  * src8  + btmp7  * src9 );
221cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float dst15 = (btmp10 * src10 + btmp4  * src8  + btmp9  * src9 )
222cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                          - (btmp8  * src9  + btmp11 * src10 + btmp5  * src8 );
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate determinant
225cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float det =
226cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich                src0 * dst0 + src1 * dst1 + src2 * dst2 + src3 * dst3;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (det == 0.0f) {
229cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich            return false;
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // calculate matrix inverse
233cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        final float invdet = 1.0f / det;
234cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[     mInvOffset] = dst0  * invdet;
235cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[ 1 + mInvOffset] = dst1  * invdet;
236cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[ 2 + mInvOffset] = dst2  * invdet;
237cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[ 3 + mInvOffset] = dst3  * invdet;
238cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich
239cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[ 4 + mInvOffset] = dst4  * invdet;
240cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[ 5 + mInvOffset] = dst5  * invdet;
241cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[ 6 + mInvOffset] = dst6  * invdet;
242cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[ 7 + mInvOffset] = dst7  * invdet;
243cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich
244cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[ 8 + mInvOffset] = dst8  * invdet;
245cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[ 9 + mInvOffset] = dst9  * invdet;
246cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[10 + mInvOffset] = dst10 * invdet;
247cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[11 + mInvOffset] = dst11 * invdet;
248cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich
249cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[12 + mInvOffset] = dst12 * invdet;
250cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[13 + mInvOffset] = dst13 * invdet;
251cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[14 + mInvOffset] = dst14 * invdet;
252cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        mInv[15 + mInvOffset] = dst15 * invdet;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Computes an orthographic projection matrix.
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m returns the result
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param left
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param right
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bottom
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param top
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param near
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param far
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void orthoM(float[] m, int mOffset,
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float left, float right, float bottom, float top,
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float near, float far) {
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (left == right) {
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("left == right");
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bottom == top) {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("bottom == top");
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (near == far) {
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("near == far");
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_width  = 1.0f / (right - left);
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_height = 1.0f / (top - bottom);
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_depth  = 1.0f / (far - near);
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float x =  2.0f * (r_width);
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float y =  2.0f * (r_height);
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float z = -2.0f * (r_depth);
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float tx = -(right + left) * r_width;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float ty = -(top + bottom) * r_height;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float tz = -(far + near) * r_depth;
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 0] = x;
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 5] = y;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset +10] = z;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset +12] = tx;
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset +13] = ty;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset +14] = tz;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset +15] = 1.0f;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 1] = 0.0f;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 2] = 0.0f;
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 3] = 0.0f;
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 4] = 0.0f;
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 6] = 0.0f;
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 7] = 0.0f;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 8] = 0.0f;
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 9] = 0.0f;
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[mOffset + 11] = 0.0f;
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
311043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Defines a projection matrix in terms of six clip planes.
312043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
313043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param m the float array that holds the output perspective matrix
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param offset the offset into float array m where the perspective
315043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *        matrix data is written
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param left
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param right
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bottom
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param top
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param near
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param far
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void frustumM(float[] m, int offset,
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float left, float right, float bottom, float top,
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float near, float far) {
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (left == right) {
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("left == right");
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (top == bottom) {
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("top == bottom");
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (near == far) {
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("near == far");
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (near <= 0.0f) {
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("near <= 0.0f");
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (far <= 0.0f) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("far <= 0.0f");
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_width  = 1.0f / (right - left);
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_height = 1.0f / (top - bottom);
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float r_depth  = 1.0f / (near - far);
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float x = 2.0f * (near * r_width);
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float y = 2.0f * (near * r_height);
3460a088f5d4681fd2da6f610de157bf905df787bf7Romain Guy        final float A = (right + left) * r_width;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float B = (top + bottom) * r_height;
34842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        final float C = (far + near) * r_depth;
34942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        final float D = 2.0f * (far * near * r_depth);
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 0] = x;
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 5] = y;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 8] = A;
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  9] = B;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 10] = C;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 14] = D;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 11] = -1.0f;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  1] = 0.0f;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  2] = 0.0f;
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  3] = 0.0f;
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  4] = 0.0f;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  6] = 0.0f;
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset +  7] = 0.0f;
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 12] = 0.0f;
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 13] = 0.0f;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m[offset + 15] = 0.0f;
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
369043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Defines a projection matrix in terms of a field of view angle, an
370043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * aspect ratio, and z clip planes.
371043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
372d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich     * @param m the float array that holds the perspective matrix
373d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich     * @param offset the offset into float array m where the perspective
374043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *        matrix data is written
375d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich     * @param fovy field of view in y direction, in degrees
376d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich     * @param aspect width to height aspect ratio of the viewport
377d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich     * @param zNear
378d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich     * @param zFar
379d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich     */
380d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich    public static void perspectiveM(float[] m, int offset,
381d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich          float fovy, float aspect, float zNear, float zFar) {
382d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        float f = 1.0f / (float) Math.tan(fovy * (Math.PI / 360.0));
383d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        float rangeReciprocal = 1.0f / (zNear - zFar);
384d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich
385d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 0] = f / aspect;
386d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 1] = 0.0f;
387d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 2] = 0.0f;
388d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 3] = 0.0f;
389d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich
390d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 4] = 0.0f;
391d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 5] = f;
392d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 6] = 0.0f;
393d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 7] = 0.0f;
394d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich
395d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 8] = 0.0f;
396d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 9] = 0.0f;
397d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 10] = (zFar + zNear) * rangeReciprocal;
398d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 11] = -1.0f;
399d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich
400d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 12] = 0.0f;
401d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 13] = 0.0f;
4027c80244afb9098c75b127c2d785bb6e5b03d68c5Jack Palevich        m[offset + 14] = 2.0f * zFar * zNear * rangeReciprocal;
403d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich        m[offset + 15] = 0.0f;
404d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich    }
405d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich
406d793299e875a97dc73e04e3beb2a2865563dccdbJack Palevich    /**
407043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Computes the length of a vector.
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x x coordinate of a vector
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y y coordinate of a vector
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z z coordinate of a vector
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the length of a vector
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static float length(float x, float y, float z) {
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (float) Math.sqrt(x * x + y * y + z * z);
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets matrix m to the identity matrix.
420043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sm returns the result
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param smOffset index into sm where the result matrix starts
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void setIdentityM(float[] sm, int smOffset) {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<16 ; i++) {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[smOffset + i] = 0;
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for(int i = 0; i < 16; i += 5) {
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[smOffset + i] = 1.0f;
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
434043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Scales matrix m by x, y, and z, putting the result in sm.
435043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * <p>
436043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * m and sm must not overlap.
437043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sm returns the result
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param smOffset index into sm where the result matrix starts
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m source matrix
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the source matrix starts
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x scale factor x
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y scale factor y
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z scale factor z
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void scaleM(float[] sm, int smOffset,
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] m, int mOffset,
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x, float y, float z) {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int smi = smOffset + i;
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mi = mOffset + i;
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[     smi] = m[     mi] * x;
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[ 4 + smi] = m[ 4 + mi] * y;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[ 8 + smi] = m[ 8 + mi] * z;
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sm[12 + smi] = m[12 + mi];
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
460043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Scales matrix m in place by sx, sy, and sz.
461043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m matrix to scale
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the matrix starts
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x scale factor x
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y scale factor y
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z scale factor z
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void scaleM(float[] m, int mOffset,
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x, float y, float z) {
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mi = mOffset + i;
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m[     mi] *= x;
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m[ 4 + mi] *= y;
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m[ 8 + mi] *= z;
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
479043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Translates matrix m by x, y, and z, putting the result in tm.
480043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * <p>
481043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * m and tm must not overlap.
482043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param tm returns the result
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param tmOffset index into sm where the result matrix starts
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m source matrix
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the source matrix starts
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x translation factor x
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y translation factor y
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z translation factor z
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void translateM(float[] tm, int tmOffset,
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] m, int mOffset,
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x, float y, float z) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<12 ; i++) {
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tm[tmOffset + i] = m[mOffset + i];
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int tmi = tmOffset + i;
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mi = mOffset + i;
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tm[12 + tmi] = m[mi] * x + m[4 + mi] * y + m[8 + mi] * z +
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                m[12 + mi];
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Translates matrix m by x, y, and z in place.
507043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m matrix
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the matrix starts
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x translation factor x
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y translation factor y
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z translation factor z
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void translateM(
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] m, int mOffset,
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x, float y, float z) {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int mi = mOffset + i;
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m[12 + mi] += m[mi] * x + m[4 + mi] * y + m[8 + mi] * z;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
524043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Rotates matrix m by angle a (in degrees) around the axis (x, y, z).
525043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * <p>
526043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * m and rm must not overlap.
527043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rm returns the result
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rmOffset index into rm where the result matrix starts
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m source matrix
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the source matrix starts
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param a angle to rotate in degrees
533043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param x X axis component
534043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param y Y axis component
535043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param z Z axis component
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void rotateM(float[] rm, int rmOffset,
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] m, int mOffset,
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, float x, float y, float z) {
540cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        synchronized(sTemp) {
541cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich            setRotateM(sTemp, 0, a, x, y, z);
542cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich            multiplyMM(rm, rmOffset, m, mOffset, sTemp, 0);
543cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        }
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Rotates matrix m in place by angle a (in degrees)
548043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * around the axis (x, y, z).
549043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m source matrix
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mOffset index into m where the matrix starts
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param a angle to rotate in degrees
553043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param x X axis component
554043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param y Y axis component
555043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param z Z axis component
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void rotateM(float[] m, int mOffset,
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, float x, float y, float z) {
559cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        synchronized(sTemp) {
560cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich            setRotateM(sTemp, 0, a, x, y, z);
561cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich            multiplyMM(sTemp, 16, m, mOffset, sTemp, 0);
562cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich            System.arraycopy(sTemp, 16, m, mOffset, 16);
563cc5471c35327c1511075f5df0d45a2d57610fecbJack Palevich        }
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
567043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Creates a matrix for rotation by angle a (in degrees)
568043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * around the axis (x, y, z).
569043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * <p>
570043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * An optimized path will be used for rotation about a major axis
571043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * (e.g. x=1.0f y=0.0f z=0.0f).
572043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rm returns the result
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rmOffset index into rm where the result matrix starts
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param a angle to rotate in degrees
576043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param x X axis component
577043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param y Y axis component
578043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * @param z Z axis component
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void setRotateM(float[] rm, int rmOffset,
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float a, float x, float y, float z) {
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 3] = 0;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 7] = 0;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 11]= 0;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 12]= 0;
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 13]= 0;
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 14]= 0;
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 15]= 1;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a *= (float) (Math.PI / 180.0f);
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float s = (float) Math.sin(a);
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float c = (float) Math.cos(a);
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (1.0f == x && 0.0f == y && 0.0f == z) {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 5] = c;   rm[rmOffset + 10]= c;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 6] = s;   rm[rmOffset + 9] = -s;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 1] = 0;   rm[rmOffset + 2] = 0;
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 4] = 0;   rm[rmOffset + 8] = 0;
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 0] = 1;
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (0.0f == x && 1.0f == y && 0.0f == z) {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 0] = c;   rm[rmOffset + 10]= c;
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 8] = s;   rm[rmOffset + 2] = -s;
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 1] = 0;   rm[rmOffset + 4] = 0;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 6] = 0;   rm[rmOffset + 9] = 0;
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 5] = 1;
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (0.0f == x && 0.0f == y && 1.0f == z) {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 0] = c;   rm[rmOffset + 5] = c;
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 1] = s;   rm[rmOffset + 4] = -s;
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 2] = 0;   rm[rmOffset + 6] = 0;
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 8] = 0;   rm[rmOffset + 9] = 0;
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 10]= 1;
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float len = length(x, y, z);
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (1.0f != len) {
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float recipLen = 1.0f / len;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                x *= recipLen;
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                y *= recipLen;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                z *= recipLen;
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float nc = 1.0f - c;
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float xy = x * y;
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float yz = y * z;
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float zx = z * x;
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float xs = x * s;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float ys = y * s;
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float zs = z * s;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  0] = x*x*nc +  c;
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  4] =  xy*nc - zs;
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  8] =  zx*nc + ys;
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  1] =  xy*nc + zs;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  5] = y*y*nc +  c;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  9] =  yz*nc - xs;
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  2] =  zx*nc - ys;
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset +  6] =  yz*nc + xs;
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rm[rmOffset + 10] = z*z*nc +  c;
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
638043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Converts Euler angles to a rotation matrix.
639043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     *
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rm returns the result
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rmOffset index into rm where the result matrix starts
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x angle of rotation, in degrees
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y angle of rotation, in degrees
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param z angle of rotation, in degrees
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void setRotateEulerM(float[] rm, int rmOffset,
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float x, float y, float z) {
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        x *= (float) (Math.PI / 180.0f);
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        y *= (float) (Math.PI / 180.0f);
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        z *= (float) (Math.PI / 180.0f);
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float cx = (float) Math.cos(x);
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float sx = (float) Math.sin(x);
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float cy = (float) Math.cos(y);
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float sy = (float) Math.sin(y);
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float cz = (float) Math.cos(z);
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float sz = (float) Math.sin(z);
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float cxsy = cx * sy;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float sxsy = sx * sy;
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 0]  =   cy * cz;
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 1]  =  -cy * sz;
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 2]  =   sy;
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 3]  =  0.0f;
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 4]  =  cxsy * cz + cx * sz;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 5]  = -cxsy * sz + cx * cz;
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 6]  =  -sx * cy;
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 7]  =  0.0f;
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 8]  = -sxsy * cz + sx * sz;
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 9]  =  sxsy * sz + sx * cz;
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 10] =  cx * cy;
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 11] =  0.0f;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 12] =  0.0f;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 13] =  0.0f;
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 14] =  0.0f;
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rm[rmOffset + 15] =  1.0f;
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
680355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
681355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich    /**
682043d13ad4b67b57fa8ba1fa35f48ff5bcc0f0141Andy McFadden     * Defines a viewing transformation in terms of an eye point, a center of
683355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * view, and an up vector.
684355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     *
685355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param rm returns the result
686355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param rmOffset index into rm where the result matrix starts
687355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param eyeX eye point X
688355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param eyeY eye point Y
689355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param eyeZ eye point Z
690355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param centerX center of view X
691355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param centerY center of view Y
692355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param centerZ center of view Z
693355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param upX up vector X
694355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param upY up vector Y
695355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     * @param upZ up vector Z
696355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich     */
697355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich    public static void setLookAtM(float[] rm, int rmOffset,
698355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich            float eyeX, float eyeY, float eyeZ,
699355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich            float centerX, float centerY, float centerZ, float upX, float upY,
700355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich            float upZ) {
701355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
702355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        // See the OpenGL GLUT documentation for gluLookAt for a description
703355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        // of the algorithm. We implement it in a straightforward way:
704355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
705355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float fx = centerX - eyeX;
706355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float fy = centerY - eyeY;
707355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float fz = centerZ - eyeZ;
708355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
709355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        // Normalize f
710355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float rlf = 1.0f / Matrix.length(fx, fy, fz);
711355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        fx *= rlf;
712355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        fy *= rlf;
713355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        fz *= rlf;
714355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
715355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        // compute s = f x up (x means "cross product")
716355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float sx = fy * upZ - fz * upY;
717355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float sy = fz * upX - fx * upZ;
718355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float sz = fx * upY - fy * upX;
719355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
720355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        // and normalize s
721355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float rls = 1.0f / Matrix.length(sx, sy, sz);
722355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        sx *= rls;
723355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        sy *= rls;
724355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        sz *= rls;
725355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
726355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        // compute u = s x f
727355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float ux = sy * fz - sz * fy;
728355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float uy = sz * fx - sx * fz;
729355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        float uz = sx * fy - sy * fx;
730355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
731355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 0] = sx;
732355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 1] = ux;
733355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 2] = -fx;
734355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 3] = 0.0f;
735355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
736355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 4] = sy;
737355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 5] = uy;
738355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 6] = -fy;
739355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 7] = 0.0f;
740355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
741355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 8] = sz;
742355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 9] = uz;
743355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 10] = -fz;
744355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 11] = 0.0f;
745355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
746355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 12] = 0.0f;
747355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 13] = 0.0f;
748355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 14] = 0.0f;
749355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        rm[rmOffset + 15] = 1.0f;
750355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich
751355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich        translateM(rm, rmOffset, -eyeX, -eyeY, -eyeZ);
752355c20cb9276148fd9b7074c5199aedeb497406eJack Palevich    }
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
754