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 3x3 Matrix
     25  * @name mat3
     26  */
     27 var mat3 = {};
     28 
     29 /**
     30  * Creates a new identity mat3
     31  *
     32  * @returns {mat3} a new 3x3 matrix
     33  */
     34 mat3.create = function() {
     35     var out = new glMatrix.ARRAY_TYPE(9);
     36     out[0] = 1;
     37     out[1] = 0;
     38     out[2] = 0;
     39     out[3] = 0;
     40     out[4] = 1;
     41     out[5] = 0;
     42     out[6] = 0;
     43     out[7] = 0;
     44     out[8] = 1;
     45     return out;
     46 };
     47 
     48 /**
     49  * Copies the upper-left 3x3 values into the given mat3.
     50  *
     51  * @param {mat3} out the receiving 3x3 matrix
     52  * @param {mat4} a   the source 4x4 matrix
     53  * @returns {mat3} out
     54  */
     55 mat3.fromMat4 = function(out, a) {
     56     out[0] = a[0];
     57     out[1] = a[1];
     58     out[2] = a[2];
     59     out[3] = a[4];
     60     out[4] = a[5];
     61     out[5] = a[6];
     62     out[6] = a[8];
     63     out[7] = a[9];
     64     out[8] = a[10];
     65     return out;
     66 };
     67 
     68 /**
     69  * Creates a new mat3 initialized with values from an existing matrix
     70  *
     71  * @param {mat3} a matrix to clone
     72  * @returns {mat3} a new 3x3 matrix
     73  */
     74 mat3.clone = function(a) {
     75     var out = new glMatrix.ARRAY_TYPE(9);
     76     out[0] = a[0];
     77     out[1] = a[1];
     78     out[2] = a[2];
     79     out[3] = a[3];
     80     out[4] = a[4];
     81     out[5] = a[5];
     82     out[6] = a[6];
     83     out[7] = a[7];
     84     out[8] = a[8];
     85     return out;
     86 };
     87 
     88 /**
     89  * Copy the values from one mat3 to another
     90  *
     91  * @param {mat3} out the receiving matrix
     92  * @param {mat3} a the source matrix
     93  * @returns {mat3} out
     94  */
     95 mat3.copy = function(out, a) {
     96     out[0] = a[0];
     97     out[1] = a[1];
     98     out[2] = a[2];
     99     out[3] = a[3];
    100     out[4] = a[4];
    101     out[5] = a[5];
    102     out[6] = a[6];
    103     out[7] = a[7];
    104     out[8] = a[8];
    105     return out;
    106 };
    107 
    108 /**
    109  * Set a mat3 to the identity matrix
    110  *
    111  * @param {mat3} out the receiving matrix
    112  * @returns {mat3} out
    113  */
    114 mat3.identity = function(out) {
    115     out[0] = 1;
    116     out[1] = 0;
    117     out[2] = 0;
    118     out[3] = 0;
    119     out[4] = 1;
    120     out[5] = 0;
    121     out[6] = 0;
    122     out[7] = 0;
    123     out[8] = 1;
    124     return out;
    125 };
    126 
    127 /**
    128  * Transpose the values of a mat3
    129  *
    130  * @param {mat3} out the receiving matrix
    131  * @param {mat3} a the source matrix
    132  * @returns {mat3} out
    133  */
    134 mat3.transpose = function(out, a) {
    135     // If we are transposing ourselves we can skip a few steps but have to cache some values
    136     if (out === a) {
    137         var a01 = a[1], a02 = a[2], a12 = a[5];
    138         out[1] = a[3];
    139         out[2] = a[6];
    140         out[3] = a01;
    141         out[5] = a[7];
    142         out[6] = a02;
    143         out[7] = a12;
    144     } else {
    145         out[0] = a[0];
    146         out[1] = a[3];
    147         out[2] = a[6];
    148         out[3] = a[1];
    149         out[4] = a[4];
    150         out[5] = a[7];
    151         out[6] = a[2];
    152         out[7] = a[5];
    153         out[8] = a[8];
    154     }
    155 
    156     return out;
    157 };
    158 
    159 /**
    160  * Inverts a mat3
    161  *
    162  * @param {mat3} out the receiving matrix
    163  * @param {mat3} a the source matrix
    164  * @returns {mat3} out
    165  */
    166 mat3.invert = function(out, a) {
    167     var a00 = a[0], a01 = a[1], a02 = a[2],
    168         a10 = a[3], a11 = a[4], a12 = a[5],
    169         a20 = a[6], a21 = a[7], a22 = a[8],
    170 
    171         b01 = a22 * a11 - a12 * a21,
    172         b11 = -a22 * a10 + a12 * a20,
    173         b21 = a21 * a10 - a11 * a20,
    174 
    175         // Calculate the determinant
    176         det = a00 * b01 + a01 * b11 + a02 * b21;
    177 
    178     if (!det) {
    179         return null;
    180     }
    181     det = 1.0 / det;
    182 
    183     out[0] = b01 * det;
    184     out[1] = (-a22 * a01 + a02 * a21) * det;
    185     out[2] = (a12 * a01 - a02 * a11) * det;
    186     out[3] = b11 * det;
    187     out[4] = (a22 * a00 - a02 * a20) * det;
    188     out[5] = (-a12 * a00 + a02 * a10) * det;
    189     out[6] = b21 * det;
    190     out[7] = (-a21 * a00 + a01 * a20) * det;
    191     out[8] = (a11 * a00 - a01 * a10) * det;
    192     return out;
    193 };
    194 
    195 /**
    196  * Calculates the adjugate of a mat3
    197  *
    198  * @param {mat3} out the receiving matrix
    199  * @param {mat3} a the source matrix
    200  * @returns {mat3} out
    201  */
    202 mat3.adjoint = function(out, a) {
    203     var a00 = a[0], a01 = a[1], a02 = a[2],
    204         a10 = a[3], a11 = a[4], a12 = a[5],
    205         a20 = a[6], a21 = a[7], a22 = a[8];
    206 
    207     out[0] = (a11 * a22 - a12 * a21);
    208     out[1] = (a02 * a21 - a01 * a22);
    209     out[2] = (a01 * a12 - a02 * a11);
    210     out[3] = (a12 * a20 - a10 * a22);
    211     out[4] = (a00 * a22 - a02 * a20);
    212     out[5] = (a02 * a10 - a00 * a12);
    213     out[6] = (a10 * a21 - a11 * a20);
    214     out[7] = (a01 * a20 - a00 * a21);
    215     out[8] = (a00 * a11 - a01 * a10);
    216     return out;
    217 };
    218 
    219 /**
    220  * Calculates the determinant of a mat3
    221  *
    222  * @param {mat3} a the source matrix
    223  * @returns {Number} determinant of a
    224  */
    225 mat3.determinant = function (a) {
    226     var a00 = a[0], a01 = a[1], a02 = a[2],
    227         a10 = a[3], a11 = a[4], a12 = a[5],
    228         a20 = a[6], a21 = a[7], a22 = a[8];
    229 
    230     return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
    231 };
    232 
    233 /**
    234  * Multiplies two mat3's
    235  *
    236  * @param {mat3} out the receiving matrix
    237  * @param {mat3} a the first operand
    238  * @param {mat3} b the second operand
    239  * @returns {mat3} out
    240  */
    241 mat3.multiply = function (out, a, b) {
    242     var a00 = a[0], a01 = a[1], a02 = a[2],
    243         a10 = a[3], a11 = a[4], a12 = a[5],
    244         a20 = a[6], a21 = a[7], a22 = a[8],
    245 
    246         b00 = b[0], b01 = b[1], b02 = b[2],
    247         b10 = b[3], b11 = b[4], b12 = b[5],
    248         b20 = b[6], b21 = b[7], b22 = b[8];
    249 
    250     out[0] = b00 * a00 + b01 * a10 + b02 * a20;
    251     out[1] = b00 * a01 + b01 * a11 + b02 * a21;
    252     out[2] = b00 * a02 + b01 * a12 + b02 * a22;
    253 
    254     out[3] = b10 * a00 + b11 * a10 + b12 * a20;
    255     out[4] = b10 * a01 + b11 * a11 + b12 * a21;
    256     out[5] = b10 * a02 + b11 * a12 + b12 * a22;
    257 
    258     out[6] = b20 * a00 + b21 * a10 + b22 * a20;
    259     out[7] = b20 * a01 + b21 * a11 + b22 * a21;
    260     out[8] = b20 * a02 + b21 * a12 + b22 * a22;
    261     return out;
    262 };
    263 
    264 /**
    265  * Alias for {@link mat3.multiply}
    266  * @function
    267  */
    268 mat3.mul = mat3.multiply;
    269 
    270 /**
    271  * Translate a mat3 by the given vector
    272  *
    273  * @param {mat3} out the receiving matrix
    274  * @param {mat3} a the matrix to translate
    275  * @param {vec2} v vector to translate by
    276  * @returns {mat3} out
    277  */
    278 mat3.translate = function(out, a, v) {
    279     var a00 = a[0], a01 = a[1], a02 = a[2],
    280         a10 = a[3], a11 = a[4], a12 = a[5],
    281         a20 = a[6], a21 = a[7], a22 = a[8],
    282         x = v[0], y = v[1];
    283 
    284     out[0] = a00;
    285     out[1] = a01;
    286     out[2] = a02;
    287 
    288     out[3] = a10;
    289     out[4] = a11;
    290     out[5] = a12;
    291 
    292     out[6] = x * a00 + y * a10 + a20;
    293     out[7] = x * a01 + y * a11 + a21;
    294     out[8] = x * a02 + y * a12 + a22;
    295     return out;
    296 };
    297 
    298 /**
    299  * Rotates a mat3 by the given angle
    300  *
    301  * @param {mat3} out the receiving matrix
    302  * @param {mat3} a the matrix to rotate
    303  * @param {Number} rad the angle to rotate the matrix by
    304  * @returns {mat3} out
    305  */
    306 mat3.rotate = function (out, a, rad) {
    307     var a00 = a[0], a01 = a[1], a02 = a[2],
    308         a10 = a[3], a11 = a[4], a12 = a[5],
    309         a20 = a[6], a21 = a[7], a22 = a[8],
    310 
    311         s = Math.sin(rad),
    312         c = Math.cos(rad);
    313 
    314     out[0] = c * a00 + s * a10;
    315     out[1] = c * a01 + s * a11;
    316     out[2] = c * a02 + s * a12;
    317 
    318     out[3] = c * a10 - s * a00;
    319     out[4] = c * a11 - s * a01;
    320     out[5] = c * a12 - s * a02;
    321 
    322     out[6] = a20;
    323     out[7] = a21;
    324     out[8] = a22;
    325     return out;
    326 };
    327 
    328 /**
    329  * Scales the mat3 by the dimensions in the given vec2
    330  *
    331  * @param {mat3} out the receiving matrix
    332  * @param {mat3} a the matrix to rotate
    333  * @param {vec2} v the vec2 to scale the matrix by
    334  * @returns {mat3} out
    335  **/
    336 mat3.scale = function(out, a, v) {
    337     var x = v[0], y = v[1];
    338 
    339     out[0] = x * a[0];
    340     out[1] = x * a[1];
    341     out[2] = x * a[2];
    342 
    343     out[3] = y * a[3];
    344     out[4] = y * a[4];
    345     out[5] = y * a[5];
    346 
    347     out[6] = a[6];
    348     out[7] = a[7];
    349     out[8] = a[8];
    350     return out;
    351 };
    352 
    353 /**
    354  * Creates a matrix from a vector translation
    355  * This is equivalent to (but much faster than):
    356  *
    357  *     mat3.identity(dest);
    358  *     mat3.translate(dest, dest, vec);
    359  *
    360  * @param {mat3} out mat3 receiving operation result
    361  * @param {vec2} v Translation vector
    362  * @returns {mat3} out
    363  */
    364 mat3.fromTranslation = function(out, v) {
    365     out[0] = 1;
    366     out[1] = 0;
    367     out[2] = 0;
    368     out[3] = 0;
    369     out[4] = 1;
    370     out[5] = 0;
    371     out[6] = v[0];
    372     out[7] = v[1];
    373     out[8] = 1;
    374     return out;
    375 }
    376 
    377 /**
    378  * Creates a matrix from a given angle
    379  * This is equivalent to (but much faster than):
    380  *
    381  *     mat3.identity(dest);
    382  *     mat3.rotate(dest, dest, rad);
    383  *
    384  * @param {mat3} out mat3 receiving operation result
    385  * @param {Number} rad the angle to rotate the matrix by
    386  * @returns {mat3} out
    387  */
    388 mat3.fromRotation = function(out, rad) {
    389     var s = Math.sin(rad), c = Math.cos(rad);
    390 
    391     out[0] = c;
    392     out[1] = s;
    393     out[2] = 0;
    394 
    395     out[3] = -s;
    396     out[4] = c;
    397     out[5] = 0;
    398 
    399     out[6] = 0;
    400     out[7] = 0;
    401     out[8] = 1;
    402     return out;
    403 }
    404 
    405 /**
    406  * Creates a matrix from a vector scaling
    407  * This is equivalent to (but much faster than):
    408  *
    409  *     mat3.identity(dest);
    410  *     mat3.scale(dest, dest, vec);
    411  *
    412  * @param {mat3} out mat3 receiving operation result
    413  * @param {vec2} v Scaling vector
    414  * @returns {mat3} out
    415  */
    416 mat3.fromScaling = function(out, v) {
    417     out[0] = v[0];
    418     out[1] = 0;
    419     out[2] = 0;
    420 
    421     out[3] = 0;
    422     out[4] = v[1];
    423     out[5] = 0;
    424 
    425     out[6] = 0;
    426     out[7] = 0;
    427     out[8] = 1;
    428     return out;
    429 }
    430 
    431 /**
    432  * Copies the values from a mat2d into a mat3
    433  *
    434  * @param {mat3} out the receiving matrix
    435  * @param {mat2d} a the matrix to copy
    436  * @returns {mat3} out
    437  **/
    438 mat3.fromMat2d = function(out, a) {
    439     out[0] = a[0];
    440     out[1] = a[1];
    441     out[2] = 0;
    442 
    443     out[3] = a[2];
    444     out[4] = a[3];
    445     out[5] = 0;
    446 
    447     out[6] = a[4];
    448     out[7] = a[5];
    449     out[8] = 1;
    450     return out;
    451 };
    452 
    453 /**
    454 * Calculates a 3x3 matrix from the given quaternion
    455 *
    456 * @param {mat3} out mat3 receiving operation result
    457 * @param {quat} q Quaternion to create matrix from
    458 *
    459 * @returns {mat3} out
    460 */
    461 mat3.fromQuat = function (out, q) {
    462     var x = q[0], y = q[1], z = q[2], w = q[3],
    463         x2 = x + x,
    464         y2 = y + y,
    465         z2 = z + z,
    466 
    467         xx = x * x2,
    468         yx = y * x2,
    469         yy = y * y2,
    470         zx = z * x2,
    471         zy = z * y2,
    472         zz = z * z2,
    473         wx = w * x2,
    474         wy = w * y2,
    475         wz = w * z2;
    476 
    477     out[0] = 1 - yy - zz;
    478     out[3] = yx - wz;
    479     out[6] = zx + wy;
    480 
    481     out[1] = yx + wz;
    482     out[4] = 1 - xx - zz;
    483     out[7] = zy - wx;
    484 
    485     out[2] = zx - wy;
    486     out[5] = zy + wx;
    487     out[8] = 1 - xx - yy;
    488 
    489     return out;
    490 };
    491 
    492 /**
    493 * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
    494 *
    495 * @param {mat3} out mat3 receiving operation result
    496 * @param {mat4} a Mat4 to derive the normal matrix from
    497 *
    498 * @returns {mat3} out
    499 */
    500 mat3.normalFromMat4 = function (out, a) {
    501     var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
    502         a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
    503         a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
    504         a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
    505 
    506         b00 = a00 * a11 - a01 * a10,
    507         b01 = a00 * a12 - a02 * a10,
    508         b02 = a00 * a13 - a03 * a10,
    509         b03 = a01 * a12 - a02 * a11,
    510         b04 = a01 * a13 - a03 * a11,
    511         b05 = a02 * a13 - a03 * a12,
    512         b06 = a20 * a31 - a21 * a30,
    513         b07 = a20 * a32 - a22 * a30,
    514         b08 = a20 * a33 - a23 * a30,
    515         b09 = a21 * a32 - a22 * a31,
    516         b10 = a21 * a33 - a23 * a31,
    517         b11 = a22 * a33 - a23 * a32,
    518 
    519         // Calculate the determinant
    520         det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
    521 
    522     if (!det) {
    523         return null;
    524     }
    525     det = 1.0 / det;
    526 
    527     out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
    528     out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
    529     out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
    530 
    531     out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
    532     out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
    533     out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
    534 
    535     out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
    536     out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
    537     out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
    538 
    539     return out;
    540 };
    541 
    542 /**
    543  * Returns a string representation of a mat3
    544  *
    545  * @param {mat3} mat matrix to represent as a string
    546  * @returns {String} string representation of the matrix
    547  */
    548 mat3.str = function (a) {
    549     return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
    550                     a[3] + ', ' + a[4] + ', ' + a[5] + ', ' +
    551                     a[6] + ', ' + a[7] + ', ' + a[8] + ')';
    552 };
    553 
    554 /**
    555  * Returns Frobenius norm of a mat3
    556  *
    557  * @param {mat3} a the matrix to calculate Frobenius norm of
    558  * @returns {Number} Frobenius norm
    559  */
    560 mat3.frob = function (a) {
    561     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)))
    562 };
    563 
    564 
    565 module.exports = mat3;
    566