166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
366a37686207944273ced825e0e8b6b6375f8c3deJamie GennisRedistribution and use in source and binary forms, with or without modification,
466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisare permitted provided that the following conditions are met:
566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  * Redistributions of source code must retain the above copyright notice, this
766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    list of conditions and the following disclaimer.
866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  * Redistributions in binary form must reproduce the above copyright notice,
966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    this list of conditions and the following disclaimer in the documentation
1066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    and/or other materials provided with the distribution.
1166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
1266a37686207944273ced825e0e8b6b6375f8c3deJamie GennisTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1366a37686207944273ced825e0e8b6b6375f8c3deJamie GennisANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1466a37686207944273ced825e0e8b6b6375f8c3deJamie GennisWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1566a37686207944273ced825e0e8b6b6375f8c3deJamie GennisDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
1666a37686207944273ced825e0e8b6b6375f8c3deJamie GennisANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1866a37686207944273ced825e0e8b6b6375f8c3deJamie GennisLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
1966a37686207944273ced825e0e8b6b6375f8c3deJamie GennisANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2166a37686207944273ced825e0e8b6b6375f8c3deJamie GennisSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
2266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
2366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
2466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @class 3x3 Matrix
2566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @name mat3
2666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
2766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisvar mat3 = {};
2866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
2966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
3066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Creates a new identity mat3
3166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
3266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} a new 3x3 matrix
3366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
3466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.create = function() {
3566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var out = new GLMAT_ARRAY_TYPE(9);
3666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = 1;
3766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = 0;
3866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = 0;
3966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = 0;
4066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = 1;
4166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = 0;
4266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = 0;
4366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = 0;
4466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = 1;
4566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
4666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
4766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
4866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
4966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Copies the upper-left 3x3 values into the given mat3.
5066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
5166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving 3x3 matrix
5266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat4} a   the source 4x4 matrix
5366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
5466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
5566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.fromMat4 = function(out, a) {
5666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = a[0];
5766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = a[1];
5866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = a[2];
5966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = a[4];
6066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = a[5];
6166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = a[6];
6266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = a[8];
6366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = a[9];
6466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = a[10];
6566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
6666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
6766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
6866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
6966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Creates a new mat3 initialized with values from an existing matrix
7066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
7166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a matrix to clone
7266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} a new 3x3 matrix
7366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
7466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.clone = function(a) {
7566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var out = new GLMAT_ARRAY_TYPE(9);
7666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = a[0];
7766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = a[1];
7866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = a[2];
7966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = a[3];
8066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = a[4];
8166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = a[5];
8266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = a[6];
8366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = a[7];
8466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = a[8];
8566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
8666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
8766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
8866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
8966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Copy the values from one mat3 to another
9066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
9166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving matrix
9266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a the source matrix
9366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
9466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
9566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.copy = function(out, a) {
9666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = a[0];
9766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = a[1];
9866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = a[2];
9966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = a[3];
10066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = a[4];
10166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = a[5];
10266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = a[6];
10366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = a[7];
10466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = a[8];
10566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
10666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
10766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
10866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
10966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Set a mat3 to the identity matrix
11066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
11166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving matrix
11266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
11366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
11466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.identity = function(out) {
11566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = 1;
11666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = 0;
11766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = 0;
11866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = 0;
11966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = 1;
12066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = 0;
12166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = 0;
12266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = 0;
12366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = 1;
12466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
12566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
12666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
12766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
12866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Transpose the values of a mat3
12966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
13066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving matrix
13166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a the source matrix
13266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
13366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
13466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.transpose = function(out, a) {
13566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    // If we are transposing ourselves we can skip a few steps but have to cache some values
13666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    if (out === a) {
13766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        var a01 = a[1], a02 = a[2], a12 = a[5];
13866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[1] = a[3];
13966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[2] = a[6];
14066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[3] = a01;
14166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[5] = a[7];
14266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[6] = a02;
14366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[7] = a12;
14466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    } else {
14566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[0] = a[0];
14666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[1] = a[3];
14766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[2] = a[6];
14866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[3] = a[1];
14966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[4] = a[4];
15066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[5] = a[7];
15166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[6] = a[2];
15266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[7] = a[5];
15366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        out[8] = a[8];
15466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    }
15566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
15666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
15766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
15866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
15966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
16066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Inverts a mat3
16166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
16266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving matrix
16366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a the source matrix
16466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
16566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
16666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.invert = function(out, a) {
16766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var a00 = a[0], a01 = a[1], a02 = a[2],
16866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a10 = a[3], a11 = a[4], a12 = a[5],
16966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a20 = a[6], a21 = a[7], a22 = a[8],
17066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
17166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        b01 = a22 * a11 - a12 * a21,
17266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        b11 = -a22 * a10 + a12 * a20,
17366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        b21 = a21 * a10 - a11 * a20,
17466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
17566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        // Calculate the determinant
17666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        det = a00 * b01 + a01 * b11 + a02 * b21;
17766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
17866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    if (!det) {
17966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        return null;
18066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    }
18166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    det = 1.0 / det;
18266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
18366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = b01 * det;
18466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = (-a22 * a01 + a02 * a21) * det;
18566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = (a12 * a01 - a02 * a11) * det;
18666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = b11 * det;
18766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = (a22 * a00 - a02 * a20) * det;
18866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = (-a12 * a00 + a02 * a10) * det;
18966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = b21 * det;
19066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = (-a21 * a00 + a01 * a20) * det;
19166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = (a11 * a00 - a01 * a10) * det;
19266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
19366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
19466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
19566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
19666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Calculates the adjugate of a mat3
19766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
19866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving matrix
19966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a the source matrix
20066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
20166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
20266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.adjoint = function(out, a) {
20366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var a00 = a[0], a01 = a[1], a02 = a[2],
20466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a10 = a[3], a11 = a[4], a12 = a[5],
20566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a20 = a[6], a21 = a[7], a22 = a[8];
20666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
20766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = (a11 * a22 - a12 * a21);
20866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = (a02 * a21 - a01 * a22);
20966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = (a01 * a12 - a02 * a11);
21066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = (a12 * a20 - a10 * a22);
21166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = (a00 * a22 - a02 * a20);
21266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = (a02 * a10 - a00 * a12);
21366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = (a10 * a21 - a11 * a20);
21466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = (a01 * a20 - a00 * a21);
21566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = (a00 * a11 - a01 * a10);
21666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
21766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
21866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
21966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
22066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Calculates the determinant of a mat3
22166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
22266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a the source matrix
22366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {Number} determinant of a
22466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
22566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.determinant = function (a) {
22666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var a00 = a[0], a01 = a[1], a02 = a[2],
22766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a10 = a[3], a11 = a[4], a12 = a[5],
22866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a20 = a[6], a21 = a[7], a22 = a[8];
22966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
23066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
23166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
23266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
23366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
23466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Multiplies two mat3's
23566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
23666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving matrix
23766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a the first operand
23866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} b the second operand
23966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
24066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
24166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.multiply = function (out, a, b) {
24266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var a00 = a[0], a01 = a[1], a02 = a[2],
24366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a10 = a[3], a11 = a[4], a12 = a[5],
24466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a20 = a[6], a21 = a[7], a22 = a[8],
24566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
24666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        b00 = b[0], b01 = b[1], b02 = b[2],
24766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        b10 = b[3], b11 = b[4], b12 = b[5],
24866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        b20 = b[6], b21 = b[7], b22 = b[8];
24966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
25066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = b00 * a00 + b01 * a10 + b02 * a20;
25166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = b00 * a01 + b01 * a11 + b02 * a21;
25266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = b00 * a02 + b01 * a12 + b02 * a22;
25366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
25466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = b10 * a00 + b11 * a10 + b12 * a20;
25566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = b10 * a01 + b11 * a11 + b12 * a21;
25666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = b10 * a02 + b11 * a12 + b12 * a22;
25766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
25866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = b20 * a00 + b21 * a10 + b22 * a20;
25966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = b20 * a01 + b21 * a11 + b22 * a21;
26066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = b20 * a02 + b21 * a12 + b22 * a22;
26166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
26266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
26366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
26466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
26566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Alias for {@link mat3.multiply}
26666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @function
26766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
26866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.mul = mat3.multiply;
26966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
27066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
27166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Translate a mat3 by the given vector
27266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
27366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving matrix
27466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a the matrix to translate
27566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {vec2} v vector to translate by
27666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
27766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
27866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.translate = function(out, a, v) {
27966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var a00 = a[0], a01 = a[1], a02 = a[2],
28066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a10 = a[3], a11 = a[4], a12 = a[5],
28166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a20 = a[6], a21 = a[7], a22 = a[8],
28266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        x = v[0], y = v[1];
28366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
28466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = a00;
28566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = a01;
28666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = a02;
28766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
28866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = a10;
28966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = a11;
29066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = a12;
29166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
29266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = x * a00 + y * a10 + a20;
29366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = x * a01 + y * a11 + a21;
29466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = x * a02 + y * a12 + a22;
29566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
29666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
29766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
29866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
29966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Rotates a mat3 by the given angle
30066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
30166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving matrix
30266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a the matrix to rotate
30366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {Number} rad the angle to rotate the matrix by
30466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
30566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
30666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.rotate = function (out, a, rad) {
30766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var a00 = a[0], a01 = a[1], a02 = a[2],
30866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a10 = a[3], a11 = a[4], a12 = a[5],
30966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        a20 = a[6], a21 = a[7], a22 = a[8],
31066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
31166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        s = Math.sin(rad),
31266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        c = Math.cos(rad);
31366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
31466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = c * a00 + s * a10;
31566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = c * a01 + s * a11;
31666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = c * a02 + s * a12;
31766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
31866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = c * a10 - s * a00;
31966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = c * a11 - s * a01;
32066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = c * a12 - s * a02;
32166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
32266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = a20;
32366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = a21;
32466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = a22;
32566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
32666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
32766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
32866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
32966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Scales the mat3 by the dimensions in the given vec2
33066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
33166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving matrix
33266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a the matrix to rotate
33366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {vec2} v the vec2 to scale the matrix by
33466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
33566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis **/
33666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.scale = function(out, a, v) {
33766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var x = v[0], y = v[2];
33866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
33966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = x * a[0];
34066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = x * a[1];
34166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = x * a[2];
34266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
34366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = y * a[3];
34466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = y * a[4];
34566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = y * a[5];
34666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
34766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = a[6];
34866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = a[7];
34966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = a[8];
35066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
35166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
35266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
35366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
35466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Copies the values from a mat2d into a mat3
35566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
35666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} out the receiving matrix
35766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} a the matrix to rotate
35866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {vec2} v the vec2 to scale the matrix by
35966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {mat3} out
36066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis **/
36166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.fromMat2d = function(out, a) {
36266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = a[0];
36366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = a[1];
36466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = 0;
36566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
36666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = a[2];
36766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = a[3];
36866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = 0;
36966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
37066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = a[4];
37166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = a[5];
37266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = 1;
37366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
37466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
37566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
37666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
37766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis* Calculates a 3x3 matrix from the given quaternion
37866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis*
37966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis* @param {mat3} out mat3 receiving operation result
38066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis* @param {quat} q Quaternion to create matrix from
38166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis*
38266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis* @returns {mat3} out
38366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis*/
38466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.fromQuat = function (out, q) {
38566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var x = q[0], y = q[1], z = q[2], w = q[3],
38666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        x2 = x + x,
38766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        y2 = y + y,
38866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        z2 = z + z,
38966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
39066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        xx = x * x2,
39166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        xy = x * y2,
39266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        xz = x * z2,
39366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        yy = y * y2,
39466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        yz = y * z2,
39566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        zz = z * z2,
39666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        wx = w * x2,
39766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        wy = w * y2,
39866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        wz = w * z2;
39966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
40066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[0] = 1 - (yy + zz);
40166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[1] = xy + wz;
40266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[2] = xz - wy;
40366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
40466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[3] = xy - wz;
40566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[4] = 1 - (xx + zz);
40666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[5] = yz + wx;
40766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
40866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[6] = xz + wy;
40966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[7] = yz - wx;
41066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    out[8] = 1 - (xx + yy);
41166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
41266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
41366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
41466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
41566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
41666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * Returns a string representation of a mat3
41766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis *
41866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @param {mat3} mat matrix to represent as a string
41966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @returns {String} string representation of the matrix
42066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
42166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennismat3.str = function (a) {
42266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
42366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                    a[3] + ', ' + a[4] + ', ' + a[5] + ', ' +
42466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                    a[6] + ', ' + a[7] + ', ' + a[8] + ')';
42566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis};
42666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
42766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisif(typeof(exports) !== 'undefined') {
42866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    exports.mat3 = mat3;
42966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis}
430