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 Samsimport android.util.Log;
210826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
220826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
239c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines/**
24c11e25c4e653124def1fb18e203b894f42106cbeTim Murray * Class for exposing the native RenderScript rs_matrix4x4 type back to the Android system.
25e29d471e5ca9781d8772d445ec7832e94856fd14Jason Sams *
26e29d471e5ca9781d8772d445ec7832e94856fd14Jason Sams **/
2725430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Samspublic class Matrix4f {
280826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
299c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
30ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Creates a new identity 4x4 matrix
31ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
3225430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams    public Matrix4f() {
330826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat = new float[16];
340826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        loadIdentity();
350826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
360826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
379c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
38ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Creates a new matrix and sets its values from the given
39ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * parameter
40ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
41ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param dataArray values to set the matrix to, must be 16
42ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *                  floats long
43ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
44e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    public Matrix4f(float[] dataArray) {
45e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        mMat = new float[16];
46e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        System.arraycopy(dataArray, 0, mMat, 0, mMat.length);
47e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    }
48e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk
499c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
50ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Return a reference to the internal array representing matrix
51ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * values. Modifying this array will also change the matrix
52ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
53ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @return internal array representing the matrix
54ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
55e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    public float[] getArray() {
56e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        return mMat;
57e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    }
58e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk
599c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
60ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Returns the value for a given row and column
61ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
62ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    * @param x column of the value to return
63ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    * @param y row of the value to return
64ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
65ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    * @return value in the yth row and xth column
66ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
67ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    public float get(int x, int y) {
68ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines        return mMat[x*4 + y];
690826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
700826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
719c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
72ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the value for a given row and column
73ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
74ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    * @param x column of the value to set
75ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    * @param y row of the value to set
76ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
77ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines    public void set(int x, int y, float v) {
78ec6f200cd8a882458c57a63e1740731f0563cbccStephen Hines        mMat[x*4 + y] = v;
790826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
800826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
819c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
82ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the matrix values to identity
83ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
840826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadIdentity() {
850826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[0] = 1;
860826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[1] = 0;
870826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[2] = 0;
880826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[3] = 0;
890826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
900826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[4] = 0;
910826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[5] = 1;
920826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[6] = 0;
930826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[7] = 0;
9425430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams
950826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[8] = 0;
960826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[9] = 0;
970826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[10] = 1;
980826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[11] = 0;
990826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
1000826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[12] = 0;
1010826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[13] = 0;
1020826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[14] = 0;
1030826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[15] = 1;
1040826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
1050826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
1069c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
107ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the values of the matrix to those of the parameter
108ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
109ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param src matrix to load the values from
110ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
11125430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams    public void load(Matrix4f src) {
112b3b89f63af148031817c046ba8023b76241c1e7cAlex Sakhartchouk        System.arraycopy(src.getArray(), 0, mMat, 0, mMat.length);
1130826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
1140826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
1159c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
1168fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    * Sets the values of the matrix to those of the parameter
1178fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    *
1188fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    * @param src matrix to load the values from
1198fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    * @hide
1208fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    */
1218fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    public void load(Matrix3f src) {
1228fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[0] = src.mMat[0];
1238fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[1] = src.mMat[1];
1248fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[2] = src.mMat[2];
1258fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[3] = 0;
1268fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams
1278fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[4] = src.mMat[3];
1288fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[5] = src.mMat[4];
1298fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[6] = src.mMat[5];
1308fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[7] = 0;
1318fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams
1328fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[8] = src.mMat[6];
1338fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[9] = src.mMat[7];
1348fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[10] = src.mMat[8];
1358fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[11] = 0;
1368fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams
1378fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[12] = 0;
1388fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[13] = 0;
1398fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[14] = 0;
1408fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams        mMat[15] = 1;
1418fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    }
1428fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams
1438fd5853c1c07c2fd3954b3c5e64702d70af31144Jason Sams    /**
144ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be a rotation matrix of certain angle
145ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * about a given axis
146ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
147ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param rot angle of rotation
148ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x rotation axis x
149ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y rotation axis y
150ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z rotation axis z
151ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
1520826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadRotate(float rot, float x, float y, float z) {
1530826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float c, s;
1540826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[3] = 0;
1550826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[7] = 0;
1560826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[11]= 0;
1570826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[12]= 0;
1580826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[13]= 0;
1590826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[14]= 0;
1600826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[15]= 1;
1610826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        rot *= (float)(java.lang.Math.PI / 180.0f);
1620826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        c = (float)java.lang.Math.cos(rot);
1630826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        s = (float)java.lang.Math.sin(rot);
16425430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams
1650826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float len = (float)java.lang.Math.sqrt(x*x + y*y + z*z);
1660826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        if (!(len != 1)) {
1670826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            float recipLen = 1.f / len;
1680826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            x *= recipLen;
1690826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            y *= recipLen;
1700826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            z *= recipLen;
1710826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        }
1720826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float nc = 1.0f - c;
1730826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float xy = x * y;
1740826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float yz = y * z;
1750826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float zx = z * x;
1760826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float xs = x * s;
1770826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        float ys = y * s;
17825430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams        float zs = z * s;
1790826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 0] = x*x*nc +  c;
1800826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 4] =  xy*nc - zs;
1810826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 8] =  zx*nc + ys;
1820826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 1] =  xy*nc + zs;
1830826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 5] = y*y*nc +  c;
1840826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 9] =  yz*nc - xs;
1850826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 2] =  zx*nc - ys;
1860826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[ 6] =  yz*nc + xs;
1870826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[10] = z*z*nc +  c;
1880826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
1890826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
1909c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
191ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be a scale matrix of given dimensions
192ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
193ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x scale component x
194ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y scale component y
195ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z scale component z
196ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
1970826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadScale(float x, float y, float z) {
1980826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        loadIdentity();
1990826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[0] = x;
2000826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[5] = y;
2010826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[10] = z;
2020826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
20325430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams
2049c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
205ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be a translation matrix of given
206ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * dimensions
207ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
208ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x translation component x
209ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y translation component y
210ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z translation component z
211ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
2120826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadTranslate(float x, float y, float z) {
2130826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        loadIdentity();
2140826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[12] = x;
2150826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[13] = y;
2160826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[14] = z;
2170826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
2180826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
2199c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
220ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be the result of multiplying two given
221ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * matrices
222ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
223ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param lhs left hand side matrix
224ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param rhs right hand side matrix
225ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
22625430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams    public void loadMultiply(Matrix4f lhs, Matrix4f rhs) {
2270826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        for (int i=0 ; i<4 ; i++) {
2280826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            float ri0 = 0;
2290826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            float ri1 = 0;
2300826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            float ri2 = 0;
2310826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            float ri3 = 0;
2320826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            for (int j=0 ; j<4 ; j++) {
2330826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams                float rhs_ij = rhs.get(i,j);
2340826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams                ri0 += lhs.get(j,0) * rhs_ij;
2350826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams                ri1 += lhs.get(j,1) * rhs_ij;
2360826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams                ri2 += lhs.get(j,2) * rhs_ij;
2370826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams                ri3 += lhs.get(j,3) * rhs_ij;
2380826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            }
2390826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            set(i,0, ri0);
2400826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            set(i,1, ri1);
2410826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            set(i,2, ri2);
2420826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams            set(i,3, ri3);
2430826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        }
2440826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
2450826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
2469c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
247ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Set current values to be an orthographic projection matrix
248ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
249ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param l location of the left vertical clipping plane
250ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param r location of the right vertical clipping plane
251ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param b location of the bottom horizontal clipping plane
252ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param t location of the top horizontal clipping plane
253ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param n location of the near clipping plane
254ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param f location of the far clipping plane
255ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
2560826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadOrtho(float l, float r, float b, float t, float n, float f) {
2570826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        loadIdentity();
2580826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[0] = 2 / (r - l);
2590826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[5] = 2 / (t - b);
2600826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[10]= -2 / (f - n);
2610826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[12]= -(r + l) / (r - l);
262b37c0a5db65cd8b72cac6a3250faddd1aecb722eJason Sams        mMat[13]= -(t + b) / (t - b);
263b37c0a5db65cd8b72cac6a3250faddd1aecb722eJason Sams        mMat[14]= -(f + n) / (f - n);
2640826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
2650826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
2669c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
267ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Set current values to be an orthographic projection matrix
268ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * with the right and bottom clipping planes set to the given
269ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * values. Left and top clipping planes are set to 0. Near and
270ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * far are set to -1, 1 respectively
271ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
272ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param w location of the right vertical clipping plane
273ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param h location of the bottom horizontal clipping plane
274ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
275ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
276e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    public void loadOrthoWindow(int w, int h) {
277e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        loadOrtho(0,w, h,0, -1,1);
278e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    }
279e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk
2809c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
281ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be a perspective projection matrix
282ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
283ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param l location of the left vertical clipping plane
284ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param r location of the right vertical clipping plane
285ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param b location of the bottom horizontal clipping plane
286ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param t location of the top horizontal clipping plane
287ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param n location of the near clipping plane, must be positive
288ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param f location of the far clipping plane, must be positive
289ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
290ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
2910826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void loadFrustum(float l, float r, float b, float t, float n, float f) {
2920826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        loadIdentity();
2930826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[0] = 2 * n / (r - l);
2940826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[5] = 2 * n / (t - b);
2950826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[8] = (r + l) / (r - l);
2960826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[9] = (t + b) / (t - b);
2970826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[10]= -(f + n) / (f - n);
2980826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[11]= -1;
2990826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[14]= -2*f*n / (f - n);
3000826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        mMat[15]= 0;
3010826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
3020826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
3039c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
304ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets current values to be a perspective projection matrix
305ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
306ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param fovy vertical field of view angle in degrees
307ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param aspect aspect ratio of the screen
308ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param near near cliping plane, must be positive
309ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param far far clipping plane, must be positive
310ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
311e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    public void loadPerspective(float fovy, float aspect, float near, float far) {
312e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        float top = near * (float)Math.tan((float) (fovy * Math.PI / 360.0f));
313e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        float bottom = -top;
314e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        float left = bottom * aspect;
315e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        float right = top * aspect;
316e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk        loadFrustum(left, right, bottom, top, near, far);
317e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk    }
318e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk
3199c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
320ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Helper function to set the current values to a perspective
321ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * projection matrix with aspect ratio defined by the parameters
322ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * and (near, far), (bottom, top) mapping to (-1, 1) at z = 0
323ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
324ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param w screen width
325ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param h screen height
326ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
327b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk    public void loadProjectionNormalized(int w, int h) {
328b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        // range -1,1 in the narrow axis at z = 0.
329b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        Matrix4f m1 = new Matrix4f();
330b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        Matrix4f m2 = new Matrix4f();
331b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
332b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        if(w > h) {
333b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk            float aspect = ((float)w) / h;
334b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk            m1.loadFrustum(-aspect,aspect,  -1,1,  1,100);
335b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        } else {
336b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk            float aspect = ((float)h) / w;
337b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk            m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
338b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        }
339b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
340b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m2.loadRotate(180, 0, 1, 0);
341b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m1.loadMultiply(m1, m2);
342b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
343b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m2.loadScale(-2, 2, 1);
344b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m1.loadMultiply(m1, m2);
345b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
346b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m2.loadTranslate(0, 0, 2);
347b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        m1.loadMultiply(m1, m2);
348b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
349b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk        load(m1);
350b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk    }
351b4d7bb6872f523b4318144202e119766ed9054edAlex Sakhartchouk
3529c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
353ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Post-multiplies the current matrix by a given parameter
354ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
355ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param rhs right hand side to multiply by
356ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
35725430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams    public void multiply(Matrix4f rhs) {
35825430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams        Matrix4f tmp = new Matrix4f();
3590826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        tmp.loadMultiply(this, rhs);
3600826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        load(tmp);
3610826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
3629c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
363ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Modifies the current matrix by post-multiplying it with a
364ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * rotation matrix of certain angle about a given axis
365ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
366ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param rot angle of rotation
367ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x rotation axis x
368ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y rotation axis y
369ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z rotation axis z
370ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
3710826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void rotate(float rot, float x, float y, float z) {
37225430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams        Matrix4f tmp = new Matrix4f();
3730826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        tmp.loadRotate(rot, x, y, z);
3740826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        multiply(tmp);
3750826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
376ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk
3779c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
378ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Modifies the current matrix by post-multiplying it with a
379ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * scale matrix of given dimensions
380ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
381ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x scale component x
382ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y scale component y
383ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z scale component z
384ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
3850826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void scale(float x, float y, float z) {
38625430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams        Matrix4f tmp = new Matrix4f();
3870826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        tmp.loadScale(x, y, z);
3880826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        multiply(tmp);
3890826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
390ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk
3919c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
392ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Modifies the current matrix by post-multiplying it with a
393ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * translation matrix of given dimensions
394ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    *
395ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param x translation component x
396ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param y translation component y
397ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * @param z translation component z
398ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
3990826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    public void translate(float x, float y, float z) {
40025430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams        Matrix4f tmp = new Matrix4f();
4010826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        tmp.loadTranslate(x, y, z);
4020826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams        multiply(tmp);
4030826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams    }
404facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    private float computeCofactor(int i, int j) {
405facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int c0 = (i+1) % 4;
406facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int c1 = (i+2) % 4;
407facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int c2 = (i+3) % 4;
408facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int r0 = (j+1) % 4;
409facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int r1 = (j+2) % 4;
410facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        int r2 = (j+3) % 4;
411facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
412facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        float minor = (mMat[c0 + 4*r0] * (mMat[c1 + 4*r1] * mMat[c2 + 4*r2] -
413facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                                            mMat[c1 + 4*r2] * mMat[c2 + 4*r1]))
414facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                     - (mMat[c0 + 4*r1] * (mMat[c1 + 4*r0] * mMat[c2 + 4*r2] -
415facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                                            mMat[c1 + 4*r2] * mMat[c2 + 4*r0]))
416facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                     + (mMat[c0 + 4*r2] * (mMat[c1 + 4*r0] * mMat[c2 + 4*r1] -
417facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                                            mMat[c1 + 4*r1] * mMat[c2 + 4*r0]));
418facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
419facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        float cofactor = ((i+j) & 1) != 0 ? -minor : minor;
420facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        return cofactor;
421facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    }
422facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
4239c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
424ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the current matrix to its inverse
425ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
426facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    public boolean inverse() {
427facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
428facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        Matrix4f result = new Matrix4f();
429facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
430facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        for (int i = 0; i < 4; ++i) {
431facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            for (int j = 0; j < 4; ++j) {
432facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                result.mMat[4*i + j] = computeCofactor(i, j);
433facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            }
434facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
435facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
436facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        // Dot product of 0th column of source and 0th row of result
437facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        float det = mMat[0]*result.mMat[0] + mMat[4]*result.mMat[1] +
438facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                     mMat[8]*result.mMat[2] + mMat[12]*result.mMat[3];
439facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
440facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        if (Math.abs(det) < 1e-6) {
441facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            return false;
442facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
443facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
444facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        det = 1.0f / det;
445facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        for (int i = 0; i < 16; ++i) {
446facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            mMat[i] = result.mMat[i] * det;
447facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
448facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
449facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        return true;
450facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    }
451facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
4529c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
453ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the current matrix to its inverse transpose
454ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
455facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    public boolean inverseTranspose() {
456facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
457facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        Matrix4f result = new Matrix4f();
458facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
459facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        for (int i = 0; i < 4; ++i) {
460facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            for (int j = 0; j < 4; ++j) {
461facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                result.mMat[4*j + i] = computeCofactor(i, j);
462facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            }
463facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
464facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
465facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        float det = mMat[0]*result.mMat[0] + mMat[4]*result.mMat[4] +
466facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk                     mMat[8]*result.mMat[8] + mMat[12]*result.mMat[12];
467facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
468facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        if (Math.abs(det) < 1e-6) {
469facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            return false;
470facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
471facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
472facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        det = 1.0f / det;
473facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        for (int i = 0; i < 16; ++i) {
474facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk            mMat[i] = result.mMat[i] * det;
475facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        }
476facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
477facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk        return true;
478facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk    }
479facd6fc4be5706f4ca5def9702a69bec94eb6adfAlex Sakhartchouk
4809c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
481ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    * Sets the current matrix to its transpose
482ec0d3353b16741c69681577eb43ccfea435eb4baAlex Sakhartchouk    */
483518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk    public void transpose() {
484518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk        for(int i = 0; i < 3; ++i) {
485518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk            for(int j = i + 1; j < 4; ++j) {
486518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk                float temp = mMat[i*4 + j];
487518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk                mMat[i*4 + j] = mMat[j*4 + i];
488518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk                mMat[j*4 + i] = temp;
489518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk            }
490518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk        }
491518f033b68649c151cc8725ea8c557eae01cc567Alex Sakhartchouk    }
4920826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams
49325430d0734d12d12ca2d2d7a9d18c0cf3c5bdc4eJason Sams    final float[] mMat;
4940826a6f90f049bf94fc39fb23ad3a736a14b96ebJason Sams}
495