1/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. 2 3Permission is hereby granted, free of charge, to any person obtaining a copy 4of this software and associated documentation files (the "Software"), to deal 5in the Software without restriction, including without limitation the rights 6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7copies of the Software, and to permit persons to whom the Software is 8furnished to do so, subject to the following conditions: 9 10The above copyright notice and this permission notice shall be included in 11all copies or substantial portions of the Software. 12 13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19THE SOFTWARE. */ 20 21var glMatrix = require("./common.js"); 22 23/** 24 * @class 3x3 Matrix 25 * @name mat3 26 */ 27var mat3 = {}; 28 29/** 30 * Creates a new identity mat3 31 * 32 * @returns {mat3} a new 3x3 matrix 33 */ 34mat3.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 */ 55mat3.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 */ 74mat3.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 */ 95mat3.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 */ 114mat3.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 */ 134mat3.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 */ 166mat3.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 */ 202mat3.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 */ 225mat3.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 */ 241mat3.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 */ 268mat3.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 */ 278mat3.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 */ 306mat3.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 **/ 336mat3.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 */ 364mat3.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 */ 388mat3.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 */ 416mat3.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 **/ 438mat3.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*/ 461mat3.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*/ 500mat3.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 */ 548mat3.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 */ 560mat3.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 565module.exports = mat3; 566