10826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams/*
2ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines * Copyright (C) 2009-2012 The Android Open Source Project
30826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams *
40826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams * Licensed under the Apache License, Version 2.0 (the "License");
50826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams * you may not use this file except in compliance with the License.
60826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams * You may obtain a copy of the License at
70826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams *
80826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams *      http://www.apache.org/licenses/LICENSE-2.0
90826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams *
100826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams * Unless required by applicable law or agreed to in writing, software
110826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams * distributed under the License is distributed on an "AS IS" BASIS,
120826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams * See the License for the specific language governing permissions and
140826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams * limitations under the License.
150826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams */
160826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
170826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Samspackage android.renderscript;
180826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
190826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Samsimport java.lang.Math;
200826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
210826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
229c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines/**
23c11e25c4e653124def1fb18e203b894f42106cbeTim Murray * Class for exposing the native RenderScript rs_matrix4x4 type back to the Android system.
24e29d471e5ca9781d8772d445ec7832e94856fd14Jason Sams *
25e29d471e5ca9781d8772d445ec7832e94856fd14Jason Sams **/
2625430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Samspublic class Matrix4f {
270826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
289c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
29ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Creates a new identity 4x4 matrix
30ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
3125430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams    public Matrix4f() {
320826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat = new float[16];
330826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        loadIdentity();
340826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
350826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
369c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
37ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Creates a new matrix and sets its values from the given
38ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * parameter
39ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
40ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param dataArray values to set the matrix to, must be 16
41ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *                  floats long
42ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
43e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    public Matrix4f(float[] dataArray) {
44e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        mMat = new float[16];
45e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        System.arraycopy(dataArray, 0, mMat, 0, mMat.length);
46e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    }
47e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk
489c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
49ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Return a reference to the internal array representing matrix
50ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * values. Modifying this array will also change the matrix
51ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
52ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @return internal array representing the matrix
53ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
54e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    public float[] getArray() {
55e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        return mMat;
56e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    }
57e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk
589c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
59ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Returns the value for a given row and column
60ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
61ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    * @param x column of the value to return
62ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    * @param y row of the value to return
63ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
64ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    * @return value in the yth row and xth column
65ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
66ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    public float get(int x, int y) {
67ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines        return mMat[x*4 + y];
680826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
690826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
709c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
71ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the value for a given row and column
72ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
73ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    * @param x column of the value to set
74ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    * @param y row of the value to set
75ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
76ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    public void set(int x, int y, float v) {
77ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines        mMat[x*4 + y] = v;
780826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
790826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
809c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
81ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the matrix values to identity
82ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
830826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadIdentity() {
840826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[0] = 1;
850826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[1] = 0;
860826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[2] = 0;
870826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[3] = 0;
880826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
890826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[4] = 0;
900826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[5] = 1;
910826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[6] = 0;
920826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[7] = 0;
9325430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams
940826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[8] = 0;
950826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[9] = 0;
960826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[10] = 1;
970826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[11] = 0;
980826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
990826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[12] = 0;
1000826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[13] = 0;
1010826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[14] = 0;
1020826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[15] = 1;
1030826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
1040826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
1059c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
106ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the values of the matrix to those of the parameter
107ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
108ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param src matrix to load the values from
109ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
11025430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams    public void load(Matrix4f src) {
111b3b89f63af148031817c046ba8023b76241c1e7cAlex Sakhartchouk        System.arraycopy(src.getArray(), 0, mMat, 0, mMat.length);
1120826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
1130826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
1149c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
1158fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    * Sets the values of the matrix to those of the parameter
1168fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    *
1178fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    * @param src matrix to load the values from
1188fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    * @hide
1198fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    */
1208fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    public void load(Matrix3f src) {
1218fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[0] = src.mMat[0];
1228fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[1] = src.mMat[1];
1238fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[2] = src.mMat[2];
1248fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[3] = 0;
1258fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams
1268fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[4] = src.mMat[3];
1278fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[5] = src.mMat[4];
1288fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[6] = src.mMat[5];
1298fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[7] = 0;
1308fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams
1318fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[8] = src.mMat[6];
1328fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[9] = src.mMat[7];
1338fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[10] = src.mMat[8];
1348fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[11] = 0;
1358fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams
1368fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[12] = 0;
1378fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[13] = 0;
1388fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[14] = 0;
1398fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[15] = 1;
1408fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    }
1418fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams
1428fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    /**
143ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be a rotation matrix of certain angle
144ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * about a given axis
145ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
146ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param rot angle of rotation
147ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x rotation axis x
148ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y rotation axis y
149ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z rotation axis z
150ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
1510826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadRotate(float rot, float x, float y, float z) {
1520826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float c, s;
1530826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[3] = 0;
1540826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[7] = 0;
1550826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[11]= 0;
1560826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[12]= 0;
1570826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[13]= 0;
1580826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[14]= 0;
1590826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[15]= 1;
1600826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        rot *= (float)(java.lang.Math.PI / 180.0f);
1610826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        c = (float)java.lang.Math.cos(rot);
1620826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        s = (float)java.lang.Math.sin(rot);
16325430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams
1640826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float len = (float)java.lang.Math.sqrt(x*x + y*y + z*z);
1650826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        if (!(len != 1)) {
1660826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            float recipLen = 1.f / len;
1670826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            x *= recipLen;
1680826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            y *= recipLen;
1690826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            z *= recipLen;
1700826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        }
1710826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float nc = 1.0f - c;
1720826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float xy = x * y;
1730826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float yz = y * z;
1740826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float zx = z * x;
1750826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float xs = x * s;
1760826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float ys = y * s;
17725430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams        float zs = z * s;
1780826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 0] = x*x*nc +  c;
1790826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 4] =  xy*nc - zs;
1800826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 8] =  zx*nc + ys;
1810826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 1] =  xy*nc + zs;
1820826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 5] = y*y*nc +  c;
1830826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 9] =  yz*nc - xs;
1840826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 2] =  zx*nc - ys;
1850826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 6] =  yz*nc + xs;
1860826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[10] = z*z*nc +  c;
1870826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
1880826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
1899c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
190ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be a scale matrix of given dimensions
191ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
192ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x scale component x
193ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y scale component y
194ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z scale component z
195ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
1960826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadScale(float x, float y, float z) {
1970826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        loadIdentity();
1980826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[0] = x;
1990826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[5] = y;
2000826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[10] = z;
2010826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
20225430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams
2039c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
204ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be a translation matrix of given
205ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * dimensions
206ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
207ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x translation component x
208ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y translation component y
209ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z translation component z
210ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
2110826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadTranslate(float x, float y, float z) {
2120826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        loadIdentity();
2130826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[12] = x;
2140826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[13] = y;
2150826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[14] = z;
2160826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
2170826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
2189c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
219ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be the result of multiplying two given
220ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * matrices
221ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
222ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param lhs left hand side matrix
223ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param rhs right hand side matrix
224ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
22525430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams    public void loadMultiply(Matrix4f lhs, Matrix4f rhs) {
2260826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        for (int i=0 ; i<4 ; i++) {
2270826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            float ri0 = 0;
2280826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            float ri1 = 0;
2290826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            float ri2 = 0;
2300826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            float ri3 = 0;
2310826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            for (int j=0 ; j<4 ; j++) {
2320826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams                float rhs_ij = rhs.get(i,j);
2330826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams                ri0 += lhs.get(j,0) * rhs_ij;
2340826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams                ri1 += lhs.get(j,1) * rhs_ij;
2350826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams                ri2 += lhs.get(j,2) * rhs_ij;
2360826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams                ri3 += lhs.get(j,3) * rhs_ij;
2370826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            }
2380826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            set(i,0, ri0);
2390826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            set(i,1, ri1);
2400826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            set(i,2, ri2);
2410826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            set(i,3, ri3);
2420826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        }
2430826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
2440826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
2459c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
246ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Set current values to be an orthographic projection matrix
247ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
248ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param l location of the left vertical clipping plane
249ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param r location of the right vertical clipping plane
250ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param b location of the bottom horizontal clipping plane
251ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param t location of the top horizontal clipping plane
252ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param n location of the near clipping plane
253ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param f location of the far clipping plane
254ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
2550826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadOrtho(float l, float r, float b, float t, float n, float f) {
2560826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        loadIdentity();
2570826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[0] = 2 / (r - l);
2580826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[5] = 2 / (t - b);
2590826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[10]= -2 / (f - n);
2600826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[12]= -(r + l) / (r - l);
261b37c0a5db65cd8b72cac6a3250faddd1aecb722eJason Sams        mMat[13]= -(t + b) / (t - b);
262b37c0a5db65cd8b72cac6a3250faddd1aecb722eJason Sams        mMat[14]= -(f + n) / (f - n);
2630826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
2640826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
2659c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
266ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Set current values to be an orthographic projection matrix
267ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * with the right and bottom clipping planes set to the given
268ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * values. Left and top clipping planes are set to 0. Near and
269ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * far are set to -1, 1 respectively
270ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
271ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param w location of the right vertical clipping plane
272ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param h location of the bottom horizontal clipping plane
273ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
274ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
275e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    public void loadOrthoWindow(int w, int h) {
276e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        loadOrtho(0,w, h,0, -1,1);
277e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    }
278e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk
2799c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
280ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be a perspective projection matrix
281ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
282ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param l location of the left vertical clipping plane
283ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param r location of the right vertical clipping plane
284ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param b location of the bottom horizontal clipping plane
285ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param t location of the top horizontal clipping plane
286ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param n location of the near clipping plane, must be positive
287ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param f location of the far clipping plane, must be positive
288ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
289ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
2900826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadFrustum(float l, float r, float b, float t, float n, float f) {
2910826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        loadIdentity();
2920826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[0] = 2 * n / (r - l);
2930826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[5] = 2 * n / (t - b);
2940826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[8] = (r + l) / (r - l);
2950826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[9] = (t + b) / (t - b);
2960826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[10]= -(f + n) / (f - n);
2970826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[11]= -1;
2980826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[14]= -2*f*n / (f - n);
2990826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[15]= 0;
3000826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
3010826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
3029c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
303ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be a perspective projection matrix
304ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
305ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param fovy vertical field of view angle in degrees
306ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param aspect aspect ratio of the screen
307ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param near near cliping plane, must be positive
308ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param far far clipping plane, must be positive
309ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
310e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    public void loadPerspective(float fovy, float aspect, float near, float far) {
311e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        float top = near * (float)Math.tan((float) (fovy * Math.PI / 360.0f));
312e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        float bottom = -top;
313e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        float left = bottom * aspect;
314e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        float right = top * aspect;
315e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        loadFrustum(left, right, bottom, top, near, far);
316e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    }
317e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk
3189c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
319ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Helper function to set the current values to a perspective
320ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * projection matrix with aspect ratio defined by the parameters
321ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * and (near, far), (bottom, top) mapping to (-1, 1) at z = 0
322ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
323ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param w screen width
324ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param h screen height
325ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
326b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk    public void loadProjectionNormalized(int w, int h) {
327b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        // range -1,1 in the narrow axis at z = 0.
328b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        Matrix4f m1 = new Matrix4f();
329b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        Matrix4f m2 = new Matrix4f();
330b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
331b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        if(w > h) {
332b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk            float aspect = ((float)w) / h;
333b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk            m1.loadFrustum(-aspect,aspect,  -1,1,  1,100);
334b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        } else {
335b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk            float aspect = ((float)h) / w;
336b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk            m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
337b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        }
338b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
339b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m2.loadRotate(180, 0, 1, 0);
340b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m1.loadMultiply(m1, m2);
341b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
342b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m2.loadScale(-2, 2, 1);
343b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m1.loadMultiply(m1, m2);
344b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
345b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m2.loadTranslate(0, 0, 2);
346b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m1.loadMultiply(m1, m2);
347b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
348b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        load(m1);
349b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk    }
350b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
3519c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
352ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Post-multiplies the current matrix by a given parameter
353ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
354ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param rhs right hand side to multiply by
355ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
35625430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams    public void multiply(Matrix4f rhs) {
35725430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams        Matrix4f tmp = new Matrix4f();
3580826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        tmp.loadMultiply(this, rhs);
3590826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        load(tmp);
3600826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
3619c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
362ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Modifies the current matrix by post-multiplying it with a
363ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * rotation matrix of certain angle about a given axis
364ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
365ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param rot angle of rotation
366ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x rotation axis x
367ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y rotation axis y
368ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z rotation axis z
369ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
3700826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void rotate(float rot, float x, float y, float z) {
37125430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams        Matrix4f tmp = new Matrix4f();
3720826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        tmp.loadRotate(rot, x, y, z);
3730826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        multiply(tmp);
3740826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
375ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk
3769c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
377ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Modifies the current matrix by post-multiplying it with a
378ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * scale matrix of given dimensions
379ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
380ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x scale component x
381ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y scale component y
382ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z scale component z
383ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
3840826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void scale(float x, float y, float z) {
38525430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams        Matrix4f tmp = new Matrix4f();
3860826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        tmp.loadScale(x, y, z);
3870826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        multiply(tmp);
3880826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
389ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk
3909c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
391ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Modifies the current matrix by post-multiplying it with a
392ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * translation matrix of given dimensions
393ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
394ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x translation component x
395ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y translation component y
396ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z translation component z
397ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
3980826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void translate(float x, float y, float z) {
39925430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams        Matrix4f tmp = new Matrix4f();
4000826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        tmp.loadTranslate(x, y, z);
4010826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        multiply(tmp);
4020826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
403facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    private float computeCofactor(int i, int j) {
404facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int c0 = (i+1) % 4;
405facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int c1 = (i+2) % 4;
406facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int c2 = (i+3) % 4;
407facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int r0 = (j+1) % 4;
408facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int r1 = (j+2) % 4;
409facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int r2 = (j+3) % 4;
410facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
411facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        float minor = (mMat[c0 + 4*r0] * (mMat[c1 + 4*r1] * mMat[c2 + 4*r2] -
412facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                                            mMat[c1 + 4*r2] * mMat[c2 + 4*r1]))
413facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                     - (mMat[c0 + 4*r1] * (mMat[c1 + 4*r0] * mMat[c2 + 4*r2] -
414facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                                            mMat[c1 + 4*r2] * mMat[c2 + 4*r0]))
415facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                     + (mMat[c0 + 4*r2] * (mMat[c1 + 4*r0] * mMat[c2 + 4*r1] -
416facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                                            mMat[c1 + 4*r1] * mMat[c2 + 4*r0]));
417facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
418facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        float cofactor = ((i+j) & 1) != 0 ? -minor : minor;
419facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        return cofactor;
420facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    }
421facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
4229c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
423ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the current matrix to its inverse
424ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
425facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    public boolean inverse() {
426facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
427facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        Matrix4f result = new Matrix4f();
428facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
429facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        for (int i = 0; i < 4; ++i) {
430facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            for (int j = 0; j < 4; ++j) {
431facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                result.mMat[4*i + j] = computeCofactor(i, j);
432facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            }
433facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
434facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
435facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        // Dot product of 0th column of source and 0th row of result
436facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        float det = mMat[0]*result.mMat[0] + mMat[4]*result.mMat[1] +
437facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                     mMat[8]*result.mMat[2] + mMat[12]*result.mMat[3];
438facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
439facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        if (Math.abs(det) < 1e-6) {
440facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            return false;
441facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
442facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
443facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        det = 1.0f / det;
444facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        for (int i = 0; i < 16; ++i) {
445facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            mMat[i] = result.mMat[i] * det;
446facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
447facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
448facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        return true;
449facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    }
450facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
4519c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
452ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the current matrix to its inverse transpose
453ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
454facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    public boolean inverseTranspose() {
455facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
456facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        Matrix4f result = new Matrix4f();
457facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
458facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        for (int i = 0; i < 4; ++i) {
459facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            for (int j = 0; j < 4; ++j) {
460facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                result.mMat[4*j + i] = computeCofactor(i, j);
461facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            }
462facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
463facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
464facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        float det = mMat[0]*result.mMat[0] + mMat[4]*result.mMat[4] +
465facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                     mMat[8]*result.mMat[8] + mMat[12]*result.mMat[12];
466facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
467facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        if (Math.abs(det) < 1e-6) {
468facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            return false;
469facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
470facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
471facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        det = 1.0f / det;
472facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        for (int i = 0; i < 16; ++i) {
473facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            mMat[i] = result.mMat[i] * det;
474facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
475facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
476facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        return true;
477facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    }
478facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
4799c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
480ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the current matrix to its transpose
481ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
482518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk    public void transpose() {
483518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk        for(int i = 0; i < 3; ++i) {
484518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk            for(int j = i + 1; j < 4; ++j) {
485518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk                float temp = mMat[i*4 + j];
486518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk                mMat[i*4 + j] = mMat[j*4 + i];
487518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk                mMat[j*4 + i] = temp;
488518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk            }
489518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk        }
490518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk    }
4910826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
49225430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams    final float[] mMat;
4930826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams}
494