Home | History | Annotate | Download | only in gl-matrix
      1 /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
      2 
      3 Permission is hereby granted, free of charge, to any person obtaining a copy
      4 of this software and associated documentation files (the "Software"), to deal
      5 in the Software without restriction, including without limitation the rights
      6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      7 copies of the Software, and to permit persons to whom the Software is
      8 furnished to do so, subject to the following conditions:
      9 
     10 The above copyright notice and this permission notice shall be included in
     11 all copies or substantial portions of the Software.
     12 
     13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     19 THE SOFTWARE. */
     20 
     21 var glMatrix = require("./common.js");
     22 
     23 /**
     24  * @class 4x4 Matrix
     25  * @name mat4
     26  */
     27 var mat4 = {};
     28 
     29 /**
     30  * Creates a new identity mat4
     31  *
     32  * @returns {mat4} a new 4x4 matrix
     33  */
     34 mat4.create = function() {
     35     var out = new glMatrix.ARRAY_TYPE(16);
     36     out[0] = 1;
     37     out[1] = 0;
     38     out[2] = 0;
     39     out[3] = 0;
     40     out[4] = 0;
     41     out[5] = 1;
     42     out[6] = 0;
     43     out[7] = 0;
     44     out[8] = 0;
     45     out[9] = 0;
     46     out[10] = 1;
     47     out[11] = 0;
     48     out[12] = 0;
     49     out[13] = 0;
     50     out[14] = 0;
     51     out[15] = 1;
     52     return out;
     53 };
     54 
     55 /**
     56  * Creates a new mat4 initialized with values from an existing matrix
     57  *
     58  * @param {mat4} a matrix to clone
     59  * @returns {mat4} a new 4x4 matrix
     60  */
     61 mat4.clone = function(a) {
     62     var out = new glMatrix.ARRAY_TYPE(16);
     63     out[0] = a[0];
     64     out[1] = a[1];
     65     out[2] = a[2];
     66     out[3] = a[3];
     67     out[4] = a[4];
     68     out[5] = a[5];
     69     out[6] = a[6];
     70     out[7] = a[7];
     71     out[8] = a[8];
     72     out[9] = a[9];
     73     out[10] = a[10];
     74     out[11] = a[11];
     75     out[12] = a[12];
     76     out[13] = a[13];
     77     out[14] = a[14];
     78     out[15] = a[15];
     79     return out;
     80 };
     81 
     82 /**
     83  * Copy the values from one mat4 to another
     84  *
     85  * @param {mat4} out the receiving matrix
     86  * @param {mat4} a the source matrix
     87  * @returns {mat4} out
     88  */
     89 mat4.copy = function(out, a) {
     90     out[0] = a[0];
     91     out[1] = a[1];
     92     out[2] = a[2];
     93     out[3] = a[3];
     94     out[4] = a[4];
     95     out[5] = a[5];
     96     out[6] = a[6];
     97     out[7] = a[7];
     98     out[8] = a[8];
     99     out[9] = a[9];
    100     out[10] = a[10];
    101     out[11] = a[11];
    102     out[12] = a[12];
    103     out[13] = a[13];
    104     out[14] = a[14];
    105     out[15] = a[15];
    106     return out;
    107 };
    108 
    109 /**
    110  * Set a mat4 to the identity matrix
    111  *
    112  * @param {mat4} out the receiving matrix
    113  * @returns {mat4} out
    114  */
    115 mat4.identity = function(out) {
    116     out[0] = 1;
    117     out[1] = 0;
    118     out[2] = 0;
    119     out[3] = 0;
    120     out[4] = 0;
    121     out[5] = 1;
    122     out[6] = 0;
    123     out[7] = 0;
    124     out[8] = 0;
    125     out[9] = 0;
    126     out[10] = 1;
    127     out[11] = 0;
    128     out[12] = 0;
    129     out[13] = 0;
    130     out[14] = 0;
    131     out[15] = 1;
    132     return out;
    133 };
    134 
    135 /**
    136  * Transpose the values of a mat4
    137  *
    138  * @param {mat4} out the receiving matrix
    139  * @param {mat4} a the source matrix
    140  * @returns {mat4} out
    141  */
    142 mat4.transpose = function(out, a) {
    143     // If we are transposing ourselves we can skip a few steps but have to cache some values
    144     if (out === a) {
    145         var a01 = a[1], a02 = a[2], a03 = a[3],
    146             a12 = a[6], a13 = a[7],
    147             a23 = a[11];
    148 
    149         out[1] = a[4];
    150         out[2] = a[8];
    151         out[3] = a[12];
    152         out[4] = a01;
    153         out[6] = a[9];
    154         out[7] = a[13];
    155         out[8] = a02;
    156         out[9] = a12;
    157         out[11] = a[14];
    158         out[12] = a03;
    159         out[13] = a13;
    160         out[14] = a23;
    161     } else {
    162         out[0] = a[0];
    163         out[1] = a[4];
    164         out[2] = a[8];
    165         out[3] = a[12];
    166         out[4] = a[1];
    167         out[5] = a[5];
    168         out[6] = a[9];
    169         out[7] = a[13];
    170         out[8] = a[2];
    171         out[9] = a[6];
    172         out[10] = a[10];
    173         out[11] = a[14];
    174         out[12] = a[3];
    175         out[13] = a[7];
    176         out[14] = a[11];
    177         out[15] = a[15];
    178     }
    179 
    180     return out;
    181 };
    182 
    183 /**
    184  * Inverts a mat4
    185  *
    186  * @param {mat4} out the receiving matrix
    187  * @param {mat4} a the source matrix
    188  * @returns {mat4} out
    189  */
    190 mat4.invert = function(out, a) {
    191     var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
    192         a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
    193         a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
    194         a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
    195 
    196         b00 = a00 * a11 - a01 * a10,
    197         b01 = a00 * a12 - a02 * a10,
    198         b02 = a00 * a13 - a03 * a10,
    199         b03 = a01 * a12 - a02 * a11,
    200         b04 = a01 * a13 - a03 * a11,
    201         b05 = a02 * a13 - a03 * a12,
    202         b06 = a20 * a31 - a21 * a30,
    203         b07 = a20 * a32 - a22 * a30,
    204         b08 = a20 * a33 - a23 * a30,
    205         b09 = a21 * a32 - a22 * a31,
    206         b10 = a21 * a33 - a23 * a31,
    207         b11 = a22 * a33 - a23 * a32,
    208 
    209         // Calculate the determinant
    210         det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
    211 
    212     if (!det) {
    213         return null;
    214     }
    215     det = 1.0 / det;
    216 
    217     out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
    218     out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
    219     out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
    220     out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
    221     out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
    222     out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
    223     out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
    224     out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
    225     out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
    226     out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
    227     out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
    228     out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
    229     out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
    230     out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
    231     out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
    232     out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
    233 
    234     return out;
    235 };
    236 
    237 /**
    238  * Calculates the adjugate of a mat4
    239  *
    240  * @param {mat4} out the receiving matrix
    241  * @param {mat4} a the source matrix
    242  * @returns {mat4} out
    243  */
    244 mat4.adjoint = function(out, a) {
    245     var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
    246         a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
    247         a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
    248         a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
    249 
    250     out[0]  =  (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
    251     out[1]  = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
    252     out[2]  =  (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
    253     out[3]  = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
    254     out[4]  = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
    255     out[5]  =  (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
    256     out[6]  = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
    257     out[7]  =  (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
    258     out[8]  =  (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
    259     out[9]  = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
    260     out[10] =  (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
    261     out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
    262     out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
    263     out[13] =  (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
    264     out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
    265     out[15] =  (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
    266     return out;
    267 };
    268 
    269 /**
    270  * Calculates the determinant of a mat4
    271  *
    272  * @param {mat4} a the source matrix
    273  * @returns {Number} determinant of a
    274  */
    275 mat4.determinant = function (a) {
    276     var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
    277         a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
    278         a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
    279         a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
    280 
    281         b00 = a00 * a11 - a01 * a10,
    282         b01 = a00 * a12 - a02 * a10,
    283         b02 = a00 * a13 - a03 * a10,
    284         b03 = a01 * a12 - a02 * a11,
    285         b04 = a01 * a13 - a03 * a11,
    286         b05 = a02 * a13 - a03 * a12,
    287         b06 = a20 * a31 - a21 * a30,
    288         b07 = a20 * a32 - a22 * a30,
    289         b08 = a20 * a33 - a23 * a30,
    290         b09 = a21 * a32 - a22 * a31,
    291         b10 = a21 * a33 - a23 * a31,
    292         b11 = a22 * a33 - a23 * a32;
    293 
    294     // Calculate the determinant
    295     return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
    296 };
    297 
    298 /**
    299  * Multiplies two mat4's
    300  *
    301  * @param {mat4} out the receiving matrix
    302  * @param {mat4} a the first operand
    303  * @param {mat4} b the second operand
    304  * @returns {mat4} out
    305  */
    306 mat4.multiply = function (out, a, b) {
    307     var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
    308         a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
    309         a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
    310         a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
    311 
    312     // Cache only the current line of the second matrix
    313     var b0  = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
    314     out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
    315     out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
    316     out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
    317     out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
    318 
    319     b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
    320     out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
    321     out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
    322     out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
    323     out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
    324 
    325     b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
    326     out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
    327     out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
    328     out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
    329     out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
    330 
    331     b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
    332     out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
    333     out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
    334     out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
    335     out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
    336     return out;
    337 };
    338 
    339 /**
    340  * Alias for {@link mat4.multiply}
    341  * @function
    342  */
    343 mat4.mul = mat4.multiply;
    344 
    345 /**
    346  * Translate a mat4 by the given vector
    347  *
    348  * @param {mat4} out the receiving matrix
    349  * @param {mat4} a the matrix to translate
    350  * @param {vec3} v vector to translate by
    351  * @returns {mat4} out
    352  */
    353 mat4.translate = function (out, a, v) {
    354     var x = v[0], y = v[1], z = v[2],
    355         a00, a01, a02, a03,
    356         a10, a11, a12, a13,
    357         a20, a21, a22, a23;
    358 
    359     if (a === out) {
    360         out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
    361         out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
    362         out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
    363         out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
    364     } else {
    365         a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
    366         a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
    367         a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
    368 
    369         out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
    370         out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
    371         out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
    372 
    373         out[12] = a00 * x + a10 * y + a20 * z + a[12];
    374         out[13] = a01 * x + a11 * y + a21 * z + a[13];
    375         out[14] = a02 * x + a12 * y + a22 * z + a[14];
    376         out[15] = a03 * x + a13 * y + a23 * z + a[15];
    377     }
    378 
    379     return out;
    380 };
    381 
    382 /**
    383  * Scales the mat4 by the dimensions in the given vec3
    384  *
    385  * @param {mat4} out the receiving matrix
    386  * @param {mat4} a the matrix to scale
    387  * @param {vec3} v the vec3 to scale the matrix by
    388  * @returns {mat4} out
    389  **/
    390 mat4.scale = function(out, a, v) {
    391     var x = v[0], y = v[1], z = v[2];
    392 
    393     out[0] = a[0] * x;
    394     out[1] = a[1] * x;
    395     out[2] = a[2] * x;
    396     out[3] = a[3] * x;
    397     out[4] = a[4] * y;
    398     out[5] = a[5] * y;
    399     out[6] = a[6] * y;
    400     out[7] = a[7] * y;
    401     out[8] = a[8] * z;
    402     out[9] = a[9] * z;
    403     out[10] = a[10] * z;
    404     out[11] = a[11] * z;
    405     out[12] = a[12];
    406     out[13] = a[13];
    407     out[14] = a[14];
    408     out[15] = a[15];
    409     return out;
    410 };
    411 
    412 /**
    413  * Rotates a mat4 by the given angle around the given axis
    414  *
    415  * @param {mat4} out the receiving matrix
    416  * @param {mat4} a the matrix to rotate
    417  * @param {Number} rad the angle to rotate the matrix by
    418  * @param {vec3} axis the axis to rotate around
    419  * @returns {mat4} out
    420  */
    421 mat4.rotate = function (out, a, rad, axis) {
    422     var x = axis[0], y = axis[1], z = axis[2],
    423         len = Math.sqrt(x * x + y * y + z * z),
    424         s, c, t,
    425         a00, a01, a02, a03,
    426         a10, a11, a12, a13,
    427         a20, a21, a22, a23,
    428         b00, b01, b02,
    429         b10, b11, b12,
    430         b20, b21, b22;
    431 
    432     if (Math.abs(len) < glMatrix.EPSILON) { return null; }
    433 
    434     len = 1 / len;
    435     x *= len;
    436     y *= len;
    437     z *= len;
    438 
    439     s = Math.sin(rad);
    440     c = Math.cos(rad);
    441     t = 1 - c;
    442 
    443     a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
    444     a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
    445     a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
    446 
    447     // Construct the elements of the rotation matrix
    448     b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
    449     b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
    450     b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
    451 
    452     // Perform rotation-specific matrix multiplication
    453     out[0] = a00 * b00 + a10 * b01 + a20 * b02;
    454     out[1] = a01 * b00 + a11 * b01 + a21 * b02;
    455     out[2] = a02 * b00 + a12 * b01 + a22 * b02;
    456     out[3] = a03 * b00 + a13 * b01 + a23 * b02;
    457     out[4] = a00 * b10 + a10 * b11 + a20 * b12;
    458     out[5] = a01 * b10 + a11 * b11 + a21 * b12;
    459     out[6] = a02 * b10 + a12 * b11 + a22 * b12;
    460     out[7] = a03 * b10 + a13 * b11 + a23 * b12;
    461     out[8] = a00 * b20 + a10 * b21 + a20 * b22;
    462     out[9] = a01 * b20 + a11 * b21 + a21 * b22;
    463     out[10] = a02 * b20 + a12 * b21 + a22 * b22;
    464     out[11] = a03 * b20 + a13 * b21 + a23 * b22;
    465 
    466     if (a !== out) { // If the source and destination differ, copy the unchanged last row
    467         out[12] = a[12];
    468         out[13] = a[13];
    469         out[14] = a[14];
    470         out[15] = a[15];
    471     }
    472     return out;
    473 };
    474 
    475 /**
    476  * Rotates a matrix by the given angle around the X axis
    477  *
    478  * @param {mat4} out the receiving matrix
    479  * @param {mat4} a the matrix to rotate
    480  * @param {Number} rad the angle to rotate the matrix by
    481  * @returns {mat4} out
    482  */
    483 mat4.rotateX = function (out, a, rad) {
    484     var s = Math.sin(rad),
    485         c = Math.cos(rad),
    486         a10 = a[4],
    487         a11 = a[5],
    488         a12 = a[6],
    489         a13 = a[7],
    490         a20 = a[8],
    491         a21 = a[9],
    492         a22 = a[10],
    493         a23 = a[11];
    494 
    495     if (a !== out) { // If the source and destination differ, copy the unchanged rows
    496         out[0]  = a[0];
    497         out[1]  = a[1];
    498         out[2]  = a[2];
    499         out[3]  = a[3];
    500         out[12] = a[12];
    501         out[13] = a[13];
    502         out[14] = a[14];
    503         out[15] = a[15];
    504     }
    505 
    506     // Perform axis-specific matrix multiplication
    507     out[4] = a10 * c + a20 * s;
    508     out[5] = a11 * c + a21 * s;
    509     out[6] = a12 * c + a22 * s;
    510     out[7] = a13 * c + a23 * s;
    511     out[8] = a20 * c - a10 * s;
    512     out[9] = a21 * c - a11 * s;
    513     out[10] = a22 * c - a12 * s;
    514     out[11] = a23 * c - a13 * s;
    515     return out;
    516 };
    517 
    518 /**
    519  * Rotates a matrix by the given angle around the Y axis
    520  *
    521  * @param {mat4} out the receiving matrix
    522  * @param {mat4} a the matrix to rotate
    523  * @param {Number} rad the angle to rotate the matrix by
    524  * @returns {mat4} out
    525  */
    526 mat4.rotateY = function (out, a, rad) {
    527     var s = Math.sin(rad),
    528         c = Math.cos(rad),
    529         a00 = a[0],
    530         a01 = a[1],
    531         a02 = a[2],
    532         a03 = a[3],
    533         a20 = a[8],
    534         a21 = a[9],
    535         a22 = a[10],
    536         a23 = a[11];
    537 
    538     if (a !== out) { // If the source and destination differ, copy the unchanged rows
    539         out[4]  = a[4];
    540         out[5]  = a[5];
    541         out[6]  = a[6];
    542         out[7]  = a[7];
    543         out[12] = a[12];
    544         out[13] = a[13];
    545         out[14] = a[14];
    546         out[15] = a[15];
    547     }
    548 
    549     // Perform axis-specific matrix multiplication
    550     out[0] = a00 * c - a20 * s;
    551     out[1] = a01 * c - a21 * s;
    552     out[2] = a02 * c - a22 * s;
    553     out[3] = a03 * c - a23 * s;
    554     out[8] = a00 * s + a20 * c;
    555     out[9] = a01 * s + a21 * c;
    556     out[10] = a02 * s + a22 * c;
    557     out[11] = a03 * s + a23 * c;
    558     return out;
    559 };
    560 
    561 /**
    562  * Rotates a matrix by the given angle around the Z axis
    563  *
    564  * @param {mat4} out the receiving matrix
    565  * @param {mat4} a the matrix to rotate
    566  * @param {Number} rad the angle to rotate the matrix by
    567  * @returns {mat4} out
    568  */
    569 mat4.rotateZ = function (out, a, rad) {
    570     var s = Math.sin(rad),
    571         c = Math.cos(rad),
    572         a00 = a[0],
    573         a01 = a[1],
    574         a02 = a[2],
    575         a03 = a[3],
    576         a10 = a[4],
    577         a11 = a[5],
    578         a12 = a[6],
    579         a13 = a[7];
    580 
    581     if (a !== out) { // If the source and destination differ, copy the unchanged last row
    582         out[8]  = a[8];
    583         out[9]  = a[9];
    584         out[10] = a[10];
    585         out[11] = a[11];
    586         out[12] = a[12];
    587         out[13] = a[13];
    588         out[14] = a[14];
    589         out[15] = a[15];
    590     }
    591 
    592     // Perform axis-specific matrix multiplication
    593     out[0] = a00 * c + a10 * s;
    594     out[1] = a01 * c + a11 * s;
    595     out[2] = a02 * c + a12 * s;
    596     out[3] = a03 * c + a13 * s;
    597     out[4] = a10 * c - a00 * s;
    598     out[5] = a11 * c - a01 * s;
    599     out[6] = a12 * c - a02 * s;
    600     out[7] = a13 * c - a03 * s;
    601     return out;
    602 };
    603 
    604 /**
    605  * Creates a matrix from a vector translation
    606  * This is equivalent to (but much faster than):
    607  *
    608  *     mat4.identity(dest);
    609  *     mat4.translate(dest, dest, vec);
    610  *
    611  * @param {mat4} out mat4 receiving operation result
    612  * @param {vec3} v Translation vector
    613  * @returns {mat4} out
    614  */
    615 mat4.fromTranslation = function(out, v) {
    616     out[0] = 1;
    617     out[1] = 0;
    618     out[2] = 0;
    619     out[3] = 0;
    620     out[4] = 0;
    621     out[5] = 1;
    622     out[6] = 0;
    623     out[7] = 0;
    624     out[8] = 0;
    625     out[9] = 0;
    626     out[10] = 1;
    627     out[11] = 0;
    628     out[12] = v[0];
    629     out[13] = v[1];
    630     out[14] = v[2];
    631     out[15] = 1;
    632     return out;
    633 }
    634 
    635 /**
    636  * Creates a matrix from a vector scaling
    637  * This is equivalent to (but much faster than):
    638  *
    639  *     mat4.identity(dest);
    640  *     mat4.scale(dest, dest, vec);
    641  *
    642  * @param {mat4} out mat4 receiving operation result
    643  * @param {vec3} v Scaling vector
    644  * @returns {mat4} out
    645  */
    646 mat4.fromScaling = function(out, v) {
    647     out[0] = v[0];
    648     out[1] = 0;
    649     out[2] = 0;
    650     out[3] = 0;
    651     out[4] = 0;
    652     out[5] = v[1];
    653     out[6] = 0;
    654     out[7] = 0;
    655     out[8] = 0;
    656     out[9] = 0;
    657     out[10] = v[2];
    658     out[11] = 0;
    659     out[12] = 0;
    660     out[13] = 0;
    661     out[14] = 0;
    662     out[15] = 1;
    663     return out;
    664 }
    665 
    666 /**
    667  * Creates a matrix from a given angle around a given axis
    668  * This is equivalent to (but much faster than):
    669  *
    670  *     mat4.identity(dest);
    671  *     mat4.rotate(dest, dest, rad, axis);
    672  *
    673  * @param {mat4} out mat4 receiving operation result
    674  * @param {Number} rad the angle to rotate the matrix by
    675  * @param {vec3} axis the axis to rotate around
    676  * @returns {mat4} out
    677  */
    678 mat4.fromRotation = function(out, rad, axis) {
    679     var x = axis[0], y = axis[1], z = axis[2],
    680         len = Math.sqrt(x * x + y * y + z * z),
    681         s, c, t;
    682 
    683     if (Math.abs(len) < glMatrix.EPSILON) { return null; }
    684 
    685     len = 1 / len;
    686     x *= len;
    687     y *= len;
    688     z *= len;
    689 
    690     s = Math.sin(rad);
    691     c = Math.cos(rad);
    692     t = 1 - c;
    693 
    694     // Perform rotation-specific matrix multiplication
    695     out[0] = x * x * t + c;
    696     out[1] = y * x * t + z * s;
    697     out[2] = z * x * t - y * s;
    698     out[3] = 0;
    699     out[4] = x * y * t - z * s;
    700     out[5] = y * y * t + c;
    701     out[6] = z * y * t + x * s;
    702     out[7] = 0;
    703     out[8] = x * z * t + y * s;
    704     out[9] = y * z * t - x * s;
    705     out[10] = z * z * t + c;
    706     out[11] = 0;
    707     out[12] = 0;
    708     out[13] = 0;
    709     out[14] = 0;
    710     out[15] = 1;
    711     return out;
    712 }
    713 
    714 /**
    715  * Creates a matrix from the given angle around the X axis
    716  * This is equivalent to (but much faster than):
    717  *
    718  *     mat4.identity(dest);
    719  *     mat4.rotateX(dest, dest, rad);
    720  *
    721  * @param {mat4} out mat4 receiving operation result
    722  * @param {Number} rad the angle to rotate the matrix by
    723  * @returns {mat4} out
    724  */
    725 mat4.fromXRotation = function(out, rad) {
    726     var s = Math.sin(rad),
    727         c = Math.cos(rad);
    728 
    729     // Perform axis-specific matrix multiplication
    730     out[0]  = 1;
    731     out[1]  = 0;
    732     out[2]  = 0;
    733     out[3]  = 0;
    734     out[4] = 0;
    735     out[5] = c;
    736     out[6] = s;
    737     out[7] = 0;
    738     out[8] = 0;
    739     out[9] = -s;
    740     out[10] = c;
    741     out[11] = 0;
    742     out[12] = 0;
    743     out[13] = 0;
    744     out[14] = 0;
    745     out[15] = 1;
    746     return out;
    747 }
    748 
    749 /**
    750  * Creates a matrix from the given angle around the Y axis
    751  * This is equivalent to (but much faster than):
    752  *
    753  *     mat4.identity(dest);
    754  *     mat4.rotateY(dest, dest, rad);
    755  *
    756  * @param {mat4} out mat4 receiving operation result
    757  * @param {Number} rad the angle to rotate the matrix by
    758  * @returns {mat4} out
    759  */
    760 mat4.fromYRotation = function(out, rad) {
    761     var s = Math.sin(rad),
    762         c = Math.cos(rad);
    763 
    764     // Perform axis-specific matrix multiplication
    765     out[0]  = c;
    766     out[1]  = 0;
    767     out[2]  = -s;
    768     out[3]  = 0;
    769     out[4] = 0;
    770     out[5] = 1;
    771     out[6] = 0;
    772     out[7] = 0;
    773     out[8] = s;
    774     out[9] = 0;
    775     out[10] = c;
    776     out[11] = 0;
    777     out[12] = 0;
    778     out[13] = 0;
    779     out[14] = 0;
    780     out[15] = 1;
    781     return out;
    782 }
    783 
    784 /**
    785  * Creates a matrix from the given angle around the Z axis
    786  * This is equivalent to (but much faster than):
    787  *
    788  *     mat4.identity(dest);
    789  *     mat4.rotateZ(dest, dest, rad);
    790  *
    791  * @param {mat4} out mat4 receiving operation result
    792  * @param {Number} rad the angle to rotate the matrix by
    793  * @returns {mat4} out
    794  */
    795 mat4.fromZRotation = function(out, rad) {
    796     var s = Math.sin(rad),
    797         c = Math.cos(rad);
    798 
    799     // Perform axis-specific matrix multiplication
    800     out[0]  = c;
    801     out[1]  = s;
    802     out[2]  = 0;
    803     out[3]  = 0;
    804     out[4] = -s;
    805     out[5] = c;
    806     out[6] = 0;
    807     out[7] = 0;
    808     out[8] = 0;
    809     out[9] = 0;
    810     out[10] = 1;
    811     out[11] = 0;
    812     out[12] = 0;
    813     out[13] = 0;
    814     out[14] = 0;
    815     out[15] = 1;
    816     return out;
    817 }
    818 
    819 /**
    820  * Creates a matrix from a quaternion rotation and vector translation
    821  * This is equivalent to (but much faster than):
    822  *
    823  *     mat4.identity(dest);
    824  *     mat4.translate(dest, vec);
    825  *     var quatMat = mat4.create();
    826  *     quat4.toMat4(quat, quatMat);
    827  *     mat4.multiply(dest, quatMat);
    828  *
    829  * @param {mat4} out mat4 receiving operation result
    830  * @param {quat4} q Rotation quaternion
    831  * @param {vec3} v Translation vector
    832  * @returns {mat4} out
    833  */
    834 mat4.fromRotationTranslation = function (out, q, v) {
    835     // Quaternion math
    836     var x = q[0], y = q[1], z = q[2], w = q[3],
    837         x2 = x + x,
    838         y2 = y + y,
    839         z2 = z + z,
    840 
    841         xx = x * x2,
    842         xy = x * y2,
    843         xz = x * z2,
    844         yy = y * y2,
    845         yz = y * z2,
    846         zz = z * z2,
    847         wx = w * x2,
    848         wy = w * y2,
    849         wz = w * z2;
    850 
    851     out[0] = 1 - (yy + zz);
    852     out[1] = xy + wz;
    853     out[2] = xz - wy;
    854     out[3] = 0;
    855     out[4] = xy - wz;
    856     out[5] = 1 - (xx + zz);
    857     out[6] = yz + wx;
    858     out[7] = 0;
    859     out[8] = xz + wy;
    860     out[9] = yz - wx;
    861     out[10] = 1 - (xx + yy);
    862     out[11] = 0;
    863     out[12] = v[0];
    864     out[13] = v[1];
    865     out[14] = v[2];
    866     out[15] = 1;
    867 
    868     return out;
    869 };
    870 
    871 /**
    872  * Creates a matrix from a quaternion rotation, vector translation and vector scale
    873  * This is equivalent to (but much faster than):
    874  *
    875  *     mat4.identity(dest);
    876  *     mat4.translate(dest, vec);
    877  *     var quatMat = mat4.create();
    878  *     quat4.toMat4(quat, quatMat);
    879  *     mat4.multiply(dest, quatMat);
    880  *     mat4.scale(dest, scale)
    881  *
    882  * @param {mat4} out mat4 receiving operation result
    883  * @param {quat4} q Rotation quaternion
    884  * @param {vec3} v Translation vector
    885  * @param {vec3} s Scaling vector
    886  * @returns {mat4} out
    887  */
    888 mat4.fromRotationTranslationScale = function (out, q, v, s) {
    889     // Quaternion math
    890     var x = q[0], y = q[1], z = q[2], w = q[3],
    891         x2 = x + x,
    892         y2 = y + y,
    893         z2 = z + z,
    894 
    895         xx = x * x2,
    896         xy = x * y2,
    897         xz = x * z2,
    898         yy = y * y2,
    899         yz = y * z2,
    900         zz = z * z2,
    901         wx = w * x2,
    902         wy = w * y2,
    903         wz = w * z2,
    904         sx = s[0],
    905         sy = s[1],
    906         sz = s[2];
    907 
    908     out[0] = (1 - (yy + zz)) * sx;
    909     out[1] = (xy + wz) * sx;
    910     out[2] = (xz - wy) * sx;
    911     out[3] = 0;
    912     out[4] = (xy - wz) * sy;
    913     out[5] = (1 - (xx + zz)) * sy;
    914     out[6] = (yz + wx) * sy;
    915     out[7] = 0;
    916     out[8] = (xz + wy) * sz;
    917     out[9] = (yz - wx) * sz;
    918     out[10] = (1 - (xx + yy)) * sz;
    919     out[11] = 0;
    920     out[12] = v[0];
    921     out[13] = v[1];
    922     out[14] = v[2];
    923     out[15] = 1;
    924 
    925     return out;
    926 };
    927 
    928 /**
    929  * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
    930  * This is equivalent to (but much faster than):
    931  *
    932  *     mat4.identity(dest);
    933  *     mat4.translate(dest, vec);
    934  *     mat4.translate(dest, origin);
    935  *     var quatMat = mat4.create();
    936  *     quat4.toMat4(quat, quatMat);
    937  *     mat4.multiply(dest, quatMat);
    938  *     mat4.scale(dest, scale)
    939  *     mat4.translate(dest, negativeOrigin);
    940  *
    941  * @param {mat4} out mat4 receiving operation result
    942  * @param {quat4} q Rotation quaternion
    943  * @param {vec3} v Translation vector
    944  * @param {vec3} s Scaling vector
    945  * @param {vec3} o The origin vector around which to scale and rotate
    946  * @returns {mat4} out
    947  */
    948 mat4.fromRotationTranslationScaleOrigin = function (out, q, v, s, o) {
    949   // Quaternion math
    950   var x = q[0], y = q[1], z = q[2], w = q[3],
    951       x2 = x + x,
    952       y2 = y + y,
    953       z2 = z + z,
    954 
    955       xx = x * x2,
    956       xy = x * y2,
    957       xz = x * z2,
    958       yy = y * y2,
    959       yz = y * z2,
    960       zz = z * z2,
    961       wx = w * x2,
    962       wy = w * y2,
    963       wz = w * z2,
    964 
    965       sx = s[0],
    966       sy = s[1],
    967       sz = s[2],
    968 
    969       ox = o[0],
    970       oy = o[1],
    971       oz = o[2];
    972 
    973   out[0] = (1 - (yy + zz)) * sx;
    974   out[1] = (xy + wz) * sx;
    975   out[2] = (xz - wy) * sx;
    976   out[3] = 0;
    977   out[4] = (xy - wz) * sy;
    978   out[5] = (1 - (xx + zz)) * sy;
    979   out[6] = (yz + wx) * sy;
    980   out[7] = 0;
    981   out[8] = (xz + wy) * sz;
    982   out[9] = (yz - wx) * sz;
    983   out[10] = (1 - (xx + yy)) * sz;
    984   out[11] = 0;
    985   out[12] = v[0] + ox - (out[0] * ox + out[4] * oy + out[8] * oz);
    986   out[13] = v[1] + oy - (out[1] * ox + out[5] * oy + out[9] * oz);
    987   out[14] = v[2] + oz - (out[2] * ox + out[6] * oy + out[10] * oz);
    988   out[15] = 1;
    989 
    990   return out;
    991 };
    992 
    993 mat4.fromQuat = function (out, q) {
    994     var x = q[0], y = q[1], z = q[2], w = q[3],
    995         x2 = x + x,
    996         y2 = y + y,
    997         z2 = z + z,
    998 
    999         xx = x * x2,
   1000         yx = y * x2,
   1001         yy = y * y2,
   1002         zx = z * x2,
   1003         zy = z * y2,
   1004         zz = z * z2,
   1005         wx = w * x2,
   1006         wy = w * y2,
   1007         wz = w * z2;
   1008 
   1009     out[0] = 1 - yy - zz;
   1010     out[1] = yx + wz;
   1011     out[2] = zx - wy;
   1012     out[3] = 0;
   1013 
   1014     out[4] = yx - wz;
   1015     out[5] = 1 - xx - zz;
   1016     out[6] = zy + wx;
   1017     out[7] = 0;
   1018 
   1019     out[8] = zx + wy;
   1020     out[9] = zy - wx;
   1021     out[10] = 1 - xx - yy;
   1022     out[11] = 0;
   1023 
   1024     out[12] = 0;
   1025     out[13] = 0;
   1026     out[14] = 0;
   1027     out[15] = 1;
   1028 
   1029     return out;
   1030 };
   1031 
   1032 /**
   1033  * Generates a frustum matrix with the given bounds
   1034  *
   1035  * @param {mat4} out mat4 frustum matrix will be written into
   1036  * @param {Number} left Left bound of the frustum
   1037  * @param {Number} right Right bound of the frustum
   1038  * @param {Number} bottom Bottom bound of the frustum
   1039  * @param {Number} top Top bound of the frustum
   1040  * @param {Number} near Near bound of the frustum
   1041  * @param {Number} far Far bound of the frustum
   1042  * @returns {mat4} out
   1043  */
   1044 mat4.frustum = function (out, left, right, bottom, top, near, far) {
   1045     var rl = 1 / (right - left),
   1046         tb = 1 / (top - bottom),
   1047         nf = 1 / (near - far);
   1048     out[0] = (near * 2) * rl;
   1049     out[1] = 0;
   1050     out[2] = 0;
   1051     out[3] = 0;
   1052     out[4] = 0;
   1053     out[5] = (near * 2) * tb;
   1054     out[6] = 0;
   1055     out[7] = 0;
   1056     out[8] = (right + left) * rl;
   1057     out[9] = (top + bottom) * tb;
   1058     out[10] = (far + near) * nf;
   1059     out[11] = -1;
   1060     out[12] = 0;
   1061     out[13] = 0;
   1062     out[14] = (far * near * 2) * nf;
   1063     out[15] = 0;
   1064     return out;
   1065 };
   1066 
   1067 /**
   1068  * Generates a perspective projection matrix with the given bounds
   1069  *
   1070  * @param {mat4} out mat4 frustum matrix will be written into
   1071  * @param {number} fovy Vertical field of view in radians
   1072  * @param {number} aspect Aspect ratio. typically viewport width/height
   1073  * @param {number} near Near bound of the frustum
   1074  * @param {number} far Far bound of the frustum
   1075  * @returns {mat4} out
   1076  */
   1077 mat4.perspective = function (out, fovy, aspect, near, far) {
   1078     var f = 1.0 / Math.tan(fovy / 2),
   1079         nf = 1 / (near - far);
   1080     out[0] = f / aspect;
   1081     out[1] = 0;
   1082     out[2] = 0;
   1083     out[3] = 0;
   1084     out[4] = 0;
   1085     out[5] = f;
   1086     out[6] = 0;
   1087     out[7] = 0;
   1088     out[8] = 0;
   1089     out[9] = 0;
   1090     out[10] = (far + near) * nf;
   1091     out[11] = -1;
   1092     out[12] = 0;
   1093     out[13] = 0;
   1094     out[14] = (2 * far * near) * nf;
   1095     out[15] = 0;
   1096     return out;
   1097 };
   1098 
   1099 /**
   1100  * Generates a perspective projection matrix with the given field of view.
   1101  * This is primarily useful for generating projection matrices to be used
   1102  * with the still experiemental WebVR API.
   1103  *
   1104  * @param {mat4} out mat4 frustum matrix will be written into
   1105  * @param {number} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
   1106  * @param {number} near Near bound of the frustum
   1107  * @param {number} far Far bound of the frustum
   1108  * @returns {mat4} out
   1109  */
   1110 mat4.perspectiveFromFieldOfView = function (out, fov, near, far) {
   1111     var upTan = Math.tan(fov.upDegrees * Math.PI/180.0),
   1112         downTan = Math.tan(fov.downDegrees * Math.PI/180.0),
   1113         leftTan = Math.tan(fov.leftDegrees * Math.PI/180.0),
   1114         rightTan = Math.tan(fov.rightDegrees * Math.PI/180.0),
   1115         xScale = 2.0 / (leftTan + rightTan),
   1116         yScale = 2.0 / (upTan + downTan);
   1117 
   1118     out[0] = xScale;
   1119     out[1] = 0.0;
   1120     out[2] = 0.0;
   1121     out[3] = 0.0;
   1122     out[4] = 0.0;
   1123     out[5] = yScale;
   1124     out[6] = 0.0;
   1125     out[7] = 0.0;
   1126     out[8] = -((leftTan - rightTan) * xScale * 0.5);
   1127     out[9] = ((upTan - downTan) * yScale * 0.5);
   1128     out[10] = far / (near - far);
   1129     out[11] = -1.0;
   1130     out[12] = 0.0;
   1131     out[13] = 0.0;
   1132     out[14] = (far * near) / (near - far);
   1133     out[15] = 0.0;
   1134     return out;
   1135 }
   1136 
   1137 /**
   1138  * Generates a orthogonal projection matrix with the given bounds
   1139  *
   1140  * @param {mat4} out mat4 frustum matrix will be written into
   1141  * @param {number} left Left bound of the frustum
   1142  * @param {number} right Right bound of the frustum
   1143  * @param {number} bottom Bottom bound of the frustum
   1144  * @param {number} top Top bound of the frustum
   1145  * @param {number} near Near bound of the frustum
   1146  * @param {number} far Far bound of the frustum
   1147  * @returns {mat4} out
   1148  */
   1149 mat4.ortho = function (out, left, right, bottom, top, near, far) {
   1150     var lr = 1 / (left - right),
   1151         bt = 1 / (bottom - top),
   1152         nf = 1 / (near - far);
   1153     out[0] = -2 * lr;
   1154     out[1] = 0;
   1155     out[2] = 0;
   1156     out[3] = 0;
   1157     out[4] = 0;
   1158     out[5] = -2 * bt;
   1159     out[6] = 0;
   1160     out[7] = 0;
   1161     out[8] = 0;
   1162     out[9] = 0;
   1163     out[10] = 2 * nf;
   1164     out[11] = 0;
   1165     out[12] = (left + right) * lr;
   1166     out[13] = (top + bottom) * bt;
   1167     out[14] = (far + near) * nf;
   1168     out[15] = 1;
   1169     return out;
   1170 };
   1171 
   1172 /**
   1173  * Generates a look-at matrix with the given eye position, focal point, and up axis
   1174  *
   1175  * @param {mat4} out mat4 frustum matrix will be written into
   1176  * @param {vec3} eye Position of the viewer
   1177  * @param {vec3} center Point the viewer is looking at
   1178  * @param {vec3} up vec3 pointing up
   1179  * @returns {mat4} out
   1180  */
   1181 mat4.lookAt = function (out, eye, center, up) {
   1182     var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
   1183         eyex = eye[0],
   1184         eyey = eye[1],
   1185         eyez = eye[2],
   1186         upx = up[0],
   1187         upy = up[1],
   1188         upz = up[2],
   1189         centerx = center[0],
   1190         centery = center[1],
   1191         centerz = center[2];
   1192 
   1193     if (Math.abs(eyex - centerx) < glMatrix.EPSILON &&
   1194         Math.abs(eyey - centery) < glMatrix.EPSILON &&
   1195         Math.abs(eyez - centerz) < glMatrix.EPSILON) {
   1196         return mat4.identity(out);
   1197     }
   1198 
   1199     z0 = eyex - centerx;
   1200     z1 = eyey - centery;
   1201     z2 = eyez - centerz;
   1202 
   1203     len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
   1204     z0 *= len;
   1205     z1 *= len;
   1206     z2 *= len;
   1207 
   1208     x0 = upy * z2 - upz * z1;
   1209     x1 = upz * z0 - upx * z2;
   1210     x2 = upx * z1 - upy * z0;
   1211     len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
   1212     if (!len) {
   1213         x0 = 0;
   1214         x1 = 0;
   1215         x2 = 0;
   1216     } else {
   1217         len = 1 / len;
   1218         x0 *= len;
   1219         x1 *= len;
   1220         x2 *= len;
   1221     }
   1222 
   1223     y0 = z1 * x2 - z2 * x1;
   1224     y1 = z2 * x0 - z0 * x2;
   1225     y2 = z0 * x1 - z1 * x0;
   1226 
   1227     len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
   1228     if (!len) {
   1229         y0 = 0;
   1230         y1 = 0;
   1231         y2 = 0;
   1232     } else {
   1233         len = 1 / len;
   1234         y0 *= len;
   1235         y1 *= len;
   1236         y2 *= len;
   1237     }
   1238 
   1239     out[0] = x0;
   1240     out[1] = y0;
   1241     out[2] = z0;
   1242     out[3] = 0;
   1243     out[4] = x1;
   1244     out[5] = y1;
   1245     out[6] = z1;
   1246     out[7] = 0;
   1247     out[8] = x2;
   1248     out[9] = y2;
   1249     out[10] = z2;
   1250     out[11] = 0;
   1251     out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
   1252     out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
   1253     out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
   1254     out[15] = 1;
   1255 
   1256     return out;
   1257 };
   1258 
   1259 /**
   1260  * Returns a string representation of a mat4
   1261  *
   1262  * @param {mat4} mat matrix to represent as a string
   1263  * @returns {String} string representation of the matrix
   1264  */
   1265 mat4.str = function (a) {
   1266     return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
   1267                     a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
   1268                     a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' +
   1269                     a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
   1270 };
   1271 
   1272 /**
   1273  * Returns Frobenius norm of a mat4
   1274  *
   1275  * @param {mat4} a the matrix to calculate Frobenius norm of
   1276  * @returns {Number} Frobenius norm
   1277  */
   1278 mat4.frob = function (a) {
   1279     return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) ))
   1280 };
   1281 
   1282 
   1283 module.exports = mat4;
   1284