1 /** 2 * @fileoverview gl-matrix - High performance matrix and vector operations for WebGL 3 * @author Brandon Jones 4 * @author Colin MacKenzie IV 5 * @version 1.3.7 6 */ 7 8 /* 9 * Copyright (c) 2012 Brandon Jones, Colin MacKenzie IV 10 * 11 * This software is provided 'as-is', without any express or implied 12 * warranty. In no event will the authors be held liable for any damages 13 * arising from the use of this software. 14 * 15 * Permission is granted to anyone to use this software for any purpose, 16 * including commercial applications, and to alter it and redistribute it 17 * freely, subject to the following restrictions: 18 * 19 * 1. The origin of this software must not be misrepresented; you must not 20 * claim that you wrote the original software. If you use this software 21 * in a product, an acknowledgment in the product documentation would be 22 * appreciated but is not required. 23 * 24 * 2. Altered source versions must be plainly marked as such, and must not 25 * be misrepresented as being the original software. 26 * 27 * 3. This notice may not be removed or altered from any source 28 * distribution. 29 */ 30 31 // Modification to plain glMatrix 32 // - Always use Array for MatrixType 33 // - Remove export management 34 // - Remove vec2, mat2, mat3, vec4 35 // - Comments some not needed functions 36 // - Add mat4.project and mat4.rotateVec3 37 38 (function (root) { 39 40 // Tweak to your liking 41 var FLOAT_EPSILON = 0.000001; 42 43 /** 44 * @class System-specific optimal array type 45 * @name MatrixArray 46 */ 47 var MatrixArray = Array; 48 49 /** 50 * @class 3 Dimensional Vector 51 * @name vec3 52 */ 53 var vec3 = {}; 54 55 /** 56 * Creates a new instance of a vec3 using the default array type 57 * Any javascript array-like objects containing at least 3 numeric elements can serve as a vec3 58 * 59 * @param {vec3} [vec] vec3 containing values to initialize with 60 * 61 * @returns {vec3} New vec3 62 */ 63 vec3.create = function (vec) { 64 var dest = new MatrixArray(3); 65 66 if (vec) { 67 dest[0] = vec[0]; 68 dest[1] = vec[1]; 69 dest[2] = vec[2]; 70 } else { 71 dest[0] = dest[1] = dest[2] = 0; 72 } 73 74 return dest; 75 }; 76 77 /** 78 * Creates a new instance of a vec3, initializing it with the given arguments 79 * 80 * @param {number} x X value 81 * @param {number} y Y value 82 * @param {number} z Z value 83 84 * @returns {vec3} New vec3 85 */ 86 vec3.createFrom = function (x, y, z) { 87 var dest = new MatrixArray(3); 88 89 dest[0] = x; 90 dest[1] = y; 91 dest[2] = z; 92 93 return dest; 94 }; 95 96 /** 97 * Copies the values of one vec3 to another 98 * 99 * @param {vec3} vec vec3 containing values to copy 100 * @param {vec3} dest vec3 receiving copied values 101 * 102 * @returns {vec3} dest 103 */ 104 vec3.set = function (vec, dest) { 105 dest[0] = vec[0]; 106 dest[1] = vec[1]; 107 dest[2] = vec[2]; 108 109 return dest; 110 }; 111 112 /** 113 * Compares two vectors for equality within a certain margin of error 114 * 115 * @param {vec3} a First vector 116 * @param {vec3} b Second vector 117 * 118 * @returns {Boolean} True if a is equivalent to b 119 */ 120 vec3.equal = function (a, b) { 121 return a === b || ( 122 Math.abs(a[0] - b[0]) < FLOAT_EPSILON && 123 Math.abs(a[1] - b[1]) < FLOAT_EPSILON && 124 Math.abs(a[2] - b[2]) < FLOAT_EPSILON 125 ); 126 }; 127 128 /** 129 * Performs a vector addition 130 * 131 * @param {vec3} vec First operand 132 * @param {vec3} vec2 Second operand 133 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 134 * 135 * @returns {vec3} dest if specified, vec otherwise 136 */ 137 vec3.add = function (vec, vec2, dest) { 138 if (!dest || vec === dest) { 139 vec[0] += vec2[0]; 140 vec[1] += vec2[1]; 141 vec[2] += vec2[2]; 142 return vec; 143 } 144 145 dest[0] = vec[0] + vec2[0]; 146 dest[1] = vec[1] + vec2[1]; 147 dest[2] = vec[2] + vec2[2]; 148 return dest; 149 }; 150 151 /** 152 * Performs a vector subtraction 153 * 154 * @param {vec3} vec First operand 155 * @param {vec3} vec2 Second operand 156 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 157 * 158 * @returns {vec3} dest if specified, vec otherwise 159 */ 160 vec3.subtract = function (vec, vec2, dest) { 161 if (!dest || vec === dest) { 162 vec[0] -= vec2[0]; 163 vec[1] -= vec2[1]; 164 vec[2] -= vec2[2]; 165 return vec; 166 } 167 168 dest[0] = vec[0] - vec2[0]; 169 dest[1] = vec[1] - vec2[1]; 170 dest[2] = vec[2] - vec2[2]; 171 return dest; 172 }; 173 174 /** 175 * Performs a vector multiplication 176 * 177 * @param {vec3} vec First operand 178 * @param {vec3} vec2 Second operand 179 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 180 * 181 * @returns {vec3} dest if specified, vec otherwise 182 */ 183 vec3.multiply = function (vec, vec2, dest) { 184 if (!dest || vec === dest) { 185 vec[0] *= vec2[0]; 186 vec[1] *= vec2[1]; 187 vec[2] *= vec2[2]; 188 return vec; 189 } 190 191 dest[0] = vec[0] * vec2[0]; 192 dest[1] = vec[1] * vec2[1]; 193 dest[2] = vec[2] * vec2[2]; 194 return dest; 195 }; 196 197 /** 198 * Negates the components of a vec3 199 * 200 * @param {vec3} vec vec3 to negate 201 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 202 * 203 * @returns {vec3} dest if specified, vec otherwise 204 */ 205 vec3.negate = function (vec, dest) { 206 if (!dest) { dest = vec; } 207 208 dest[0] = -vec[0]; 209 dest[1] = -vec[1]; 210 dest[2] = -vec[2]; 211 return dest; 212 }; 213 214 /** 215 * Multiplies the components of a vec3 by a scalar value 216 * 217 * @param {vec3} vec vec3 to scale 218 * @param {number} val Value to scale by 219 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 220 * 221 * @returns {vec3} dest if specified, vec otherwise 222 */ 223 vec3.scale = function (vec, val, dest) { 224 if (!dest || vec === dest) { 225 vec[0] *= val; 226 vec[1] *= val; 227 vec[2] *= val; 228 return vec; 229 } 230 231 dest[0] = vec[0] * val; 232 dest[1] = vec[1] * val; 233 dest[2] = vec[2] * val; 234 return dest; 235 }; 236 237 /** 238 * Generates a unit vector of the same direction as the provided vec3 239 * If vector length is 0, returns [0, 0, 0] 240 * 241 * @param {vec3} vec vec3 to normalize 242 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 243 * 244 * @returns {vec3} dest if specified, vec otherwise 245 */ 246 vec3.normalize = function (vec, dest) { 247 if (!dest) { dest = vec; } 248 249 var x = vec[0], y = vec[1], z = vec[2], 250 len = Math.sqrt(x * x + y * y + z * z); 251 252 if (!len) { 253 dest[0] = 0; 254 dest[1] = 0; 255 dest[2] = 0; 256 return dest; 257 } else if (len === 1) { 258 dest[0] = x; 259 dest[1] = y; 260 dest[2] = z; 261 return dest; 262 } 263 264 len = 1 / len; 265 dest[0] = x * len; 266 dest[1] = y * len; 267 dest[2] = z * len; 268 return dest; 269 }; 270 271 /** 272 * Generates the cross product of two vec3s 273 * 274 * @param {vec3} vec First operand 275 * @param {vec3} vec2 Second operand 276 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 277 * 278 * @returns {vec3} dest if specified, vec otherwise 279 */ 280 vec3.cross = function (vec, vec2, dest) { 281 if (!dest) { dest = vec; } 282 283 var x = vec[0], y = vec[1], z = vec[2], 284 x2 = vec2[0], y2 = vec2[1], z2 = vec2[2]; 285 286 dest[0] = y * z2 - z * y2; 287 dest[1] = z * x2 - x * z2; 288 dest[2] = x * y2 - y * x2; 289 return dest; 290 }; 291 292 /** 293 * Caclulates the length of a vec3 294 * 295 * @param {vec3} vec vec3 to calculate length of 296 * 297 * @returns {number} Length of vec 298 */ 299 vec3.length = function (vec) { 300 var x = vec[0], y = vec[1], z = vec[2]; 301 return Math.sqrt(x * x + y * y + z * z); 302 }; 303 304 /** 305 * Caclulates the squared length of a vec3 306 * 307 * @param {vec3} vec vec3 to calculate squared length of 308 * 309 * @returns {number} Squared Length of vec 310 */ 311 vec3.squaredLength = function (vec) { 312 var x = vec[0], y = vec[1], z = vec[2]; 313 return x * x + y * y + z * z; 314 }; 315 316 /** 317 * Caclulates the dot product of two vec3s 318 * 319 * @param {vec3} vec First operand 320 * @param {vec3} vec2 Second operand 321 * 322 * @returns {number} Dot product of vec and vec2 323 */ 324 vec3.dot = function (vec, vec2) { 325 return vec[0] * vec2[0] + vec[1] * vec2[1] + vec[2] * vec2[2]; 326 }; 327 328 /** 329 * Generates a unit vector pointing from one vector to another 330 * 331 * @param {vec3} vec Origin vec3 332 * @param {vec3} vec2 vec3 to point to 333 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 334 * 335 * @returns {vec3} dest if specified, vec otherwise 336 */ 337 /* vec3.direction = function (vec, vec2, dest) { 338 if (!dest) { dest = vec; } 339 340 var x = vec[0] - vec2[0], 341 y = vec[1] - vec2[1], 342 z = vec[2] - vec2[2], 343 len = Math.sqrt(x * x + y * y + z * z); 344 345 if (!len) { 346 dest[0] = 0; 347 dest[1] = 0; 348 dest[2] = 0; 349 return dest; 350 } 351 352 len = 1 / len; 353 dest[0] = x * len; 354 dest[1] = y * len; 355 dest[2] = z * len; 356 return dest; 357 };*/ 358 359 /** 360 * Performs a linear interpolation between two vec3 361 * 362 * @param {vec3} vec First vector 363 * @param {vec3} vec2 Second vector 364 * @param {number} lerp Interpolation amount between the two inputs 365 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 366 * 367 * @returns {vec3} dest if specified, vec otherwise 368 */ 369 vec3.lerp = function (vec, vec2, lerp, dest) { 370 if (!dest) { dest = vec; } 371 372 dest[0] = vec[0] + lerp * (vec2[0] - vec[0]); 373 dest[1] = vec[1] + lerp * (vec2[1] - vec[1]); 374 dest[2] = vec[2] + lerp * (vec2[2] - vec[2]); 375 376 return dest; 377 }; 378 379 /** 380 * Calculates the euclidian distance between two vec3 381 * 382 * Params: 383 * @param {vec3} vec First vector 384 * @param {vec3} vec2 Second vector 385 * 386 * @returns {number} Distance between vec and vec2 387 */ 388 vec3.dist = function (vec, vec2) { 389 var x = vec2[0] - vec[0], 390 y = vec2[1] - vec[1], 391 z = vec2[2] - vec[2]; 392 393 return Math.sqrt(x*x + y*y + z*z); 394 }; 395 396 // Pre-allocated to prevent unecessary garbage collection 397 var unprojectMat = null; 398 var unprojectVec = new MatrixArray(4); 399 /** 400 * Projects the specified vec3 from screen space into object space 401 * Based on the <a href="http://webcvs.freedesktop.org/mesa/Mesa/src/glu/mesa/project.c?revision=1.4&view=markup">Mesa gluUnProject implementation</a> 402 * 403 * @param {vec3} vec Screen-space vector to project 404 * @param {mat4} view View matrix 405 * @param {mat4} proj Projection matrix 406 * @param {vec4} viewport Viewport as given to gl.viewport [x, y, width, height] 407 * @param {vec3} [dest] vec3 receiving unprojected result. If not specified result is written to vec 408 * 409 * @returns {vec3} dest if specified, vec otherwise 410 */ 411 /* vec3.unproject = function (vec, view, proj, viewport, dest) { 412 if (!dest) { dest = vec; } 413 414 if(!unprojectMat) { 415 unprojectMat = mat4.create(); 416 } 417 418 var m = unprojectMat; 419 var v = unprojectVec; 420 421 v[0] = (vec[0] - viewport[0]) * 2.0 / viewport[2] - 1.0; 422 v[1] = (vec[1] - viewport[1]) * 2.0 / viewport[3] - 1.0; 423 v[2] = 2.0 * vec[2] - 1.0; 424 v[3] = 1.0; 425 426 mat4.multiply(proj, view, m); 427 if(!mat4.inverse(m)) { return null; } 428 429 mat4.multiplyVec4(m, v); 430 if(v[3] === 0.0) { return null; } 431 432 dest[0] = v[0] / v[3]; 433 dest[1] = v[1] / v[3]; 434 dest[2] = v[2] / v[3]; 435 436 return dest; 437 };*/ 438 439 /* var xUnitVec3 = vec3.createFrom(1,0,0); 440 var yUnitVec3 = vec3.createFrom(0,1,0); 441 var zUnitVec3 = vec3.createFrom(0,0,1); 442 443 var tmpvec3 = vec3.create();*/ 444 /** 445 * Generates a quaternion of rotation between two given normalized vectors 446 * 447 * @param {vec3} a Normalized source vector 448 * @param {vec3} b Normalized target vector 449 * @param {quat4} [dest] quat4 receiving operation result. 450 * 451 * @returns {quat4} dest if specified, a new quat4 otherwise 452 */ 453 /* vec3.rotationTo = function (a, b, dest) { 454 if (!dest) { dest = quat4.create(); } 455 456 var d = vec3.dot(a, b); 457 var axis = tmpvec3; 458 if (d >= 1.0) { 459 quat4.set(identityQuat4, dest); 460 } else if (d < (0.000001 - 1.0)) { 461 vec3.cross(xUnitVec3, a, axis); 462 if (vec3.length(axis) < 0.000001) 463 vec3.cross(yUnitVec3, a, axis); 464 if (vec3.length(axis) < 0.000001) 465 vec3.cross(zUnitVec3, a, axis); 466 vec3.normalize(axis); 467 quat4.fromAngleAxis(Math.PI, axis, dest); 468 } else { 469 var s = Math.sqrt((1.0 + d) * 2.0); 470 var sInv = 1.0 / s; 471 vec3.cross(a, b, axis); 472 dest[0] = axis[0] * sInv; 473 dest[1] = axis[1] * sInv; 474 dest[2] = axis[2] * sInv; 475 dest[3] = s * 0.5; 476 quat4.normalize(dest); 477 } 478 if (dest[3] > 1.0) dest[3] = 1.0; 479 else if (dest[3] < -1.0) dest[3] = -1.0; 480 return dest; 481 };*/ 482 483 /** 484 * Returns a string representation of a vector 485 * 486 * @param {vec3} vec Vector to represent as a string 487 * 488 * @returns {string} String representation of vec 489 */ 490 vec3.str = function (vec) { 491 return '[' + vec[0] + ', ' + vec[1] + ', ' + vec[2] + ']'; 492 }; 493 494 /** 495 * @class 4x4 Matrix 496 * @name mat4 497 */ 498 var mat4 = {}; 499 500 /** 501 * Creates a new instance of a mat4 using the default array type 502 * Any javascript array-like object containing at least 16 numeric elements can serve as a mat4 503 * 504 * @param {mat4} [mat] mat4 containing values to initialize with 505 * 506 * @returns {mat4} New mat4 507 */ 508 mat4.create = function (mat) { 509 var dest = new MatrixArray(16); 510 511 if (mat) { 512 dest[0] = mat[0]; 513 dest[1] = mat[1]; 514 dest[2] = mat[2]; 515 dest[3] = mat[3]; 516 dest[4] = mat[4]; 517 dest[5] = mat[5]; 518 dest[6] = mat[6]; 519 dest[7] = mat[7]; 520 dest[8] = mat[8]; 521 dest[9] = mat[9]; 522 dest[10] = mat[10]; 523 dest[11] = mat[11]; 524 dest[12] = mat[12]; 525 dest[13] = mat[13]; 526 dest[14] = mat[14]; 527 dest[15] = mat[15]; 528 } 529 530 return dest; 531 }; 532 533 /** 534 * Creates a new instance of a mat4, initializing it with the given arguments 535 * 536 * @param {number} m00 537 * @param {number} m01 538 * @param {number} m02 539 * @param {number} m03 540 * @param {number} m10 541 * @param {number} m11 542 * @param {number} m12 543 * @param {number} m13 544 * @param {number} m20 545 * @param {number} m21 546 * @param {number} m22 547 * @param {number} m23 548 * @param {number} m30 549 * @param {number} m31 550 * @param {number} m32 551 * @param {number} m33 552 553 * @returns {mat4} New mat4 554 */ 555 /* mat4.createFrom = function (m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { 556 var dest = new MatrixArray(16); 557 558 dest[0] = m00; 559 dest[1] = m01; 560 dest[2] = m02; 561 dest[3] = m03; 562 dest[4] = m10; 563 dest[5] = m11; 564 dest[6] = m12; 565 dest[7] = m13; 566 dest[8] = m20; 567 dest[9] = m21; 568 dest[10] = m22; 569 dest[11] = m23; 570 dest[12] = m30; 571 dest[13] = m31; 572 dest[14] = m32; 573 dest[15] = m33; 574 575 return dest; 576 };*/ 577 578 /** 579 * Copies the values of one mat4 to another 580 * 581 * @param {mat4} mat mat4 containing values to copy 582 * @param {mat4} dest mat4 receiving copied values 583 * 584 * @returns {mat4} dest 585 */ 586 mat4.set = function (mat, dest) { 587 dest[0] = mat[0]; 588 dest[1] = mat[1]; 589 dest[2] = mat[2]; 590 dest[3] = mat[3]; 591 dest[4] = mat[4]; 592 dest[5] = mat[5]; 593 dest[6] = mat[6]; 594 dest[7] = mat[7]; 595 dest[8] = mat[8]; 596 dest[9] = mat[9]; 597 dest[10] = mat[10]; 598 dest[11] = mat[11]; 599 dest[12] = mat[12]; 600 dest[13] = mat[13]; 601 dest[14] = mat[14]; 602 dest[15] = mat[15]; 603 return dest; 604 }; 605 606 /** 607 * Compares two matrices for equality within a certain margin of error 608 * 609 * @param {mat4} a First matrix 610 * @param {mat4} b Second matrix 611 * 612 * @returns {Boolean} True if a is equivalent to b 613 */ 614 /* mat4.equal = function (a, b) { 615 return a === b || ( 616 Math.abs(a[0] - b[0]) < FLOAT_EPSILON && 617 Math.abs(a[1] - b[1]) < FLOAT_EPSILON && 618 Math.abs(a[2] - b[2]) < FLOAT_EPSILON && 619 Math.abs(a[3] - b[3]) < FLOAT_EPSILON && 620 Math.abs(a[4] - b[4]) < FLOAT_EPSILON && 621 Math.abs(a[5] - b[5]) < FLOAT_EPSILON && 622 Math.abs(a[6] - b[6]) < FLOAT_EPSILON && 623 Math.abs(a[7] - b[7]) < FLOAT_EPSILON && 624 Math.abs(a[8] - b[8]) < FLOAT_EPSILON && 625 Math.abs(a[9] - b[9]) < FLOAT_EPSILON && 626 Math.abs(a[10] - b[10]) < FLOAT_EPSILON && 627 Math.abs(a[11] - b[11]) < FLOAT_EPSILON && 628 Math.abs(a[12] - b[12]) < FLOAT_EPSILON && 629 Math.abs(a[13] - b[13]) < FLOAT_EPSILON && 630 Math.abs(a[14] - b[14]) < FLOAT_EPSILON && 631 Math.abs(a[15] - b[15]) < FLOAT_EPSILON 632 ); 633 };*/ 634 635 /** 636 * Sets a mat4 to an identity matrix 637 * 638 * @param {mat4} dest mat4 to set 639 * 640 * @returns {mat4} dest 641 */ 642 mat4.identity = function (dest) { 643 if (!dest) { dest = mat4.create(); } 644 dest[0] = 1; 645 dest[1] = 0; 646 dest[2] = 0; 647 dest[3] = 0; 648 dest[4] = 0; 649 dest[5] = 1; 650 dest[6] = 0; 651 dest[7] = 0; 652 dest[8] = 0; 653 dest[9] = 0; 654 dest[10] = 1; 655 dest[11] = 0; 656 dest[12] = 0; 657 dest[13] = 0; 658 dest[14] = 0; 659 dest[15] = 1; 660 return dest; 661 }; 662 663 /** 664 * Transposes a mat4 (flips the values over the diagonal) 665 * 666 * @param {mat4} mat mat4 to transpose 667 * @param {mat4} [dest] mat4 receiving transposed values. If not specified result is written to mat 668 * 669 * @param {mat4} dest is specified, mat otherwise 670 */ 671 mat4.transpose = function (mat, dest) { 672 // If we are transposing ourselves we can skip a few steps but have to cache some values 673 if (!dest || mat === dest) { 674 var a01 = mat[1], a02 = mat[2], a03 = mat[3], 675 a12 = mat[6], a13 = mat[7], 676 a23 = mat[11]; 677 678 mat[1] = mat[4]; 679 mat[2] = mat[8]; 680 mat[3] = mat[12]; 681 mat[4] = a01; 682 mat[6] = mat[9]; 683 mat[7] = mat[13]; 684 mat[8] = a02; 685 mat[9] = a12; 686 mat[11] = mat[14]; 687 mat[12] = a03; 688 mat[13] = a13; 689 mat[14] = a23; 690 return mat; 691 } 692 693 dest[0] = mat[0]; 694 dest[1] = mat[4]; 695 dest[2] = mat[8]; 696 dest[3] = mat[12]; 697 dest[4] = mat[1]; 698 dest[5] = mat[5]; 699 dest[6] = mat[9]; 700 dest[7] = mat[13]; 701 dest[8] = mat[2]; 702 dest[9] = mat[6]; 703 dest[10] = mat[10]; 704 dest[11] = mat[14]; 705 dest[12] = mat[3]; 706 dest[13] = mat[7]; 707 dest[14] = mat[11]; 708 dest[15] = mat[15]; 709 return dest; 710 }; 711 712 /** 713 * Calculates the determinant of a mat4 714 * 715 * @param {mat4} mat mat4 to calculate determinant of 716 * 717 * @returns {number} determinant of mat 718 */ 719 mat4.determinant = function (mat) { 720 // Cache the matrix values (makes for huge speed increases!) 721 var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3], 722 a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7], 723 a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11], 724 a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; 725 726 return (a30 * a21 * a12 * a03 - a20 * a31 * a12 * a03 - a30 * a11 * a22 * a03 + a10 * a31 * a22 * a03 + 727 a20 * a11 * a32 * a03 - a10 * a21 * a32 * a03 - a30 * a21 * a02 * a13 + a20 * a31 * a02 * a13 + 728 a30 * a01 * a22 * a13 - a00 * a31 * a22 * a13 - a20 * a01 * a32 * a13 + a00 * a21 * a32 * a13 + 729 a30 * a11 * a02 * a23 - a10 * a31 * a02 * a23 - a30 * a01 * a12 * a23 + a00 * a31 * a12 * a23 + 730 a10 * a01 * a32 * a23 - a00 * a11 * a32 * a23 - a20 * a11 * a02 * a33 + a10 * a21 * a02 * a33 + 731 a20 * a01 * a12 * a33 - a00 * a21 * a12 * a33 - a10 * a01 * a22 * a33 + a00 * a11 * a22 * a33); 732 }; 733 734 /** 735 * Calculates the inverse matrix of a mat4 736 * 737 * @param {mat4} mat mat4 to calculate inverse of 738 * @param {mat4} [dest] mat4 receiving inverse matrix. If not specified result is written to mat 739 * 740 * @param {mat4} dest is specified, mat otherwise, null if matrix cannot be inverted 741 */ 742 mat4.inverse = function (mat, dest) { 743 if (!dest) { dest = mat; } 744 745 // Cache the matrix values (makes for huge speed increases!) 746 var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3], 747 a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7], 748 a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11], 749 a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15], 750 751 b00 = a00 * a11 - a01 * a10, 752 b01 = a00 * a12 - a02 * a10, 753 b02 = a00 * a13 - a03 * a10, 754 b03 = a01 * a12 - a02 * a11, 755 b04 = a01 * a13 - a03 * a11, 756 b05 = a02 * a13 - a03 * a12, 757 b06 = a20 * a31 - a21 * a30, 758 b07 = a20 * a32 - a22 * a30, 759 b08 = a20 * a33 - a23 * a30, 760 b09 = a21 * a32 - a22 * a31, 761 b10 = a21 * a33 - a23 * a31, 762 b11 = a22 * a33 - a23 * a32, 763 764 d = (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06), 765 invDet; 766 767 // Calculate the determinant 768 if (!d) { return null; } 769 invDet = 1 / d; 770 771 dest[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet; 772 dest[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet; 773 dest[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet; 774 dest[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet; 775 dest[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet; 776 dest[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet; 777 dest[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet; 778 dest[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet; 779 dest[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet; 780 dest[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet; 781 dest[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet; 782 dest[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet; 783 dest[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet; 784 dest[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet; 785 dest[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet; 786 dest[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet; 787 788 return dest; 789 }; 790 791 /** 792 * Copies the upper 3x3 elements of a mat4 into another mat4 793 * 794 * @param {mat4} mat mat4 containing values to copy 795 * @param {mat4} [dest] mat4 receiving copied values 796 * 797 * @returns {mat4} dest is specified, a new mat4 otherwise 798 */ 799 mat4.toRotationMat = function (mat, dest) { 800 if (!dest) { dest = mat4.create(); } 801 802 dest[0] = mat[0]; 803 dest[1] = mat[1]; 804 dest[2] = mat[2]; 805 dest[3] = mat[3]; 806 dest[4] = mat[4]; 807 dest[5] = mat[5]; 808 dest[6] = mat[6]; 809 dest[7] = mat[7]; 810 dest[8] = mat[8]; 811 dest[9] = mat[9]; 812 dest[10] = mat[10]; 813 dest[11] = mat[11]; 814 dest[12] = 0; 815 dest[13] = 0; 816 dest[14] = 0; 817 dest[15] = 1; 818 819 return dest; 820 }; 821 822 /** 823 * Copies the upper 3x3 elements of a mat4 into a mat3 824 * 825 * @param {mat4} mat mat4 containing values to copy 826 * @param {mat3} [dest] mat3 receiving copied values 827 * 828 * @returns {mat3} dest is specified, a new mat3 otherwise 829 */ 830 mat4.toMat3 = function (mat, dest) { 831 if (!dest) { dest = mat3.create(); } 832 833 dest[0] = mat[0]; 834 dest[1] = mat[1]; 835 dest[2] = mat[2]; 836 dest[3] = mat[4]; 837 dest[4] = mat[5]; 838 dest[5] = mat[6]; 839 dest[6] = mat[8]; 840 dest[7] = mat[9]; 841 dest[8] = mat[10]; 842 843 return dest; 844 }; 845 846 /** 847 * Calculates the inverse of the upper 3x3 elements of a mat4 and copies the result into a mat3 848 * The resulting matrix is useful for calculating transformed normals 849 * 850 * Params: 851 * @param {mat4} mat mat4 containing values to invert and copy 852 * @param {mat3} [dest] mat3 receiving values 853 * 854 * @returns {mat3} dest is specified, a new mat3 otherwise, null if the matrix cannot be inverted 855 */ 856 /* mat4.toInverseMat3 = function (mat, dest) { 857 // Cache the matrix values (makes for huge speed increases!) 858 var a00 = mat[0], a01 = mat[1], a02 = mat[2], 859 a10 = mat[4], a11 = mat[5], a12 = mat[6], 860 a20 = mat[8], a21 = mat[9], a22 = mat[10], 861 862 b01 = a22 * a11 - a12 * a21, 863 b11 = -a22 * a10 + a12 * a20, 864 b21 = a21 * a10 - a11 * a20, 865 866 d = a00 * b01 + a01 * b11 + a02 * b21, 867 id; 868 869 if (!d) { return null; } 870 id = 1 / d; 871 872 if (!dest) { dest = mat3.create(); } 873 874 dest[0] = b01 * id; 875 dest[1] = (-a22 * a01 + a02 * a21) * id; 876 dest[2] = (a12 * a01 - a02 * a11) * id; 877 dest[3] = b11 * id; 878 dest[4] = (a22 * a00 - a02 * a20) * id; 879 dest[5] = (-a12 * a00 + a02 * a10) * id; 880 dest[6] = b21 * id; 881 dest[7] = (-a21 * a00 + a01 * a20) * id; 882 dest[8] = (a11 * a00 - a01 * a10) * id; 883 884 return dest; 885 };*/ 886 887 /** 888 * Performs a matrix multiplication 889 * 890 * @param {mat4} mat First operand 891 * @param {mat4} mat2 Second operand 892 * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat 893 * 894 * @returns {mat4} dest if specified, mat otherwise 895 */ 896 mat4.multiply = function (mat, mat2, dest) { 897 if (!dest) { dest = mat; } 898 899 // Cache the matrix values (makes for huge speed increases!) 900 var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3]; 901 var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7]; 902 var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11]; 903 var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15]; 904 905 // Cache only the current line of the second matrix 906 var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3]; 907 dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 908 dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 909 dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 910 dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 911 912 b0 = mat2[4]; 913 b1 = mat2[5]; 914 b2 = mat2[6]; 915 b3 = mat2[7]; 916 dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 917 dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 918 dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 919 dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 920 921 b0 = mat2[8]; 922 b1 = mat2[9]; 923 b2 = mat2[10]; 924 b3 = mat2[11]; 925 dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 926 dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 927 dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 928 dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 929 930 b0 = mat2[12]; 931 b1 = mat2[13]; 932 b2 = mat2[14]; 933 b3 = mat2[15]; 934 dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 935 dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 936 dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 937 dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 938 939 return dest; 940 }; 941 942 /** 943 * Transforms a vec3 with the given matrix 944 * 4th vector component is implicitly '1' 945 * 946 * @param {mat4} mat mat4 to transform the vector with 947 * @param {vec3} vec vec3 to transform 948 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 949 * 950 * @returns {vec3} dest if specified, vec otherwise 951 */ 952 mat4.multiplyVec3 = function (mat, vec, dest) { 953 if (!dest) { dest = vec; } 954 955 var x = vec[0], y = vec[1], z = vec[2]; 956 957 dest[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12]; 958 dest[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13]; 959 dest[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14]; 960 961 return dest; 962 }; 963 964 /** 965 * Transforms a vec4 with the given matrix 966 * 967 * @param {mat4} mat mat4 to transform the vector with 968 * @param {vec4} vec vec4 to transform 969 * @param {vec4} [dest] vec4 receiving operation result. If not specified result is written to vec 970 * 971 * @returns {vec4} dest if specified, vec otherwise 972 */ 973 mat4.multiplyVec4 = function (mat, vec, dest) { 974 if (!dest) { dest = vec; } 975 976 var x = vec[0], y = vec[1], z = vec[2], w = vec[3]; 977 978 dest[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12] * w; 979 dest[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13] * w; 980 dest[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14] * w; 981 dest[3] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15] * w; 982 983 return dest; 984 }; 985 986 /** 987 Project a vec3 988 */ 989 mat4.project = function(mat, vec, dest) 990 { 991 if(!dest) { dest = vec } 992 mat4.multiplyVec4( mat, vec, dest ); 993 var iw = 1.0 / dest[3]; 994 dest[0] *= iw; 995 dest[1] *= iw; 996 dest[2] *= iw; 997 return dest; 998 } 999 1000 /** 1001 * mat4.rotateVec3 1002 * Rotate a vec3 with the given matrix 1003 * 1004 * Params: 1005 * mat - mat4 to transform the vector with 1006 * vec - vec3 to transform 1007 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec 1008 * 1009 * Returns: 1010 * dest if specified, vec otherwise 1011 */ 1012 mat4.rotateVec3 = function(mat, vec, dest) { 1013 if(!dest) { dest = vec } 1014 1015 var x = vec[0], y = vec[1], z = vec[2]; 1016 1017 dest[0] = mat[0]*x + mat[4]*y + mat[8]*z; 1018 dest[1] = mat[1]*x + mat[5]*y + mat[9]*z; 1019 dest[2] = mat[2]*x + mat[6]*y + mat[10]*z; 1020 1021 return dest; 1022 }; 1023 1024 /** 1025 * Translates a matrix by the given vector 1026 * 1027 * @param {mat4} mat mat4 to translate 1028 * @param {vec3} vec vec3 specifying the translation 1029 * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat 1030 * 1031 * @returns {mat4} dest if specified, mat otherwise 1032 */ 1033 mat4.translate = function (mat, vec, dest) { 1034 var x = vec[0], y = vec[1], z = vec[2], 1035 a00, a01, a02, a03, 1036 a10, a11, a12, a13, 1037 a20, a21, a22, a23; 1038 1039 if (!dest || mat === dest) { 1040 mat[12] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12]; 1041 mat[13] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13]; 1042 mat[14] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14]; 1043 mat[15] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15]; 1044 return mat; 1045 } 1046 1047 a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3]; 1048 a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7]; 1049 a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11]; 1050 1051 dest[0] = a00; dest[1] = a01; dest[2] = a02; dest[3] = a03; 1052 dest[4] = a10; dest[5] = a11; dest[6] = a12; dest[7] = a13; 1053 dest[8] = a20; dest[9] = a21; dest[10] = a22; dest[11] = a23; 1054 1055 dest[12] = a00 * x + a10 * y + a20 * z + mat[12]; 1056 dest[13] = a01 * x + a11 * y + a21 * z + mat[13]; 1057 dest[14] = a02 * x + a12 * y + a22 * z + mat[14]; 1058 dest[15] = a03 * x + a13 * y + a23 * z + mat[15]; 1059 return dest; 1060 }; 1061 1062 /** 1063 * Scales a matrix by the given vector 1064 * 1065 * @param {mat4} mat mat4 to scale 1066 * @param {vec3} vec vec3 specifying the scale for each axis 1067 * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat 1068 * 1069 * @param {mat4} dest if specified, mat otherwise 1070 */ 1071 mat4.scale = function (mat, vec, dest) { 1072 var x = vec[0], y = vec[1], z = vec[2]; 1073 1074 if (!dest || mat === dest) { 1075 mat[0] *= x; 1076 mat[1] *= x; 1077 mat[2] *= x; 1078 mat[3] *= x; 1079 mat[4] *= y; 1080 mat[5] *= y; 1081 mat[6] *= y; 1082 mat[7] *= y; 1083 mat[8] *= z; 1084 mat[9] *= z; 1085 mat[10] *= z; 1086 mat[11] *= z; 1087 return mat; 1088 } 1089 1090 dest[0] = mat[0] * x; 1091 dest[1] = mat[1] * x; 1092 dest[2] = mat[2] * x; 1093 dest[3] = mat[3] * x; 1094 dest[4] = mat[4] * y; 1095 dest[5] = mat[5] * y; 1096 dest[6] = mat[6] * y; 1097 dest[7] = mat[7] * y; 1098 dest[8] = mat[8] * z; 1099 dest[9] = mat[9] * z; 1100 dest[10] = mat[10] * z; 1101 dest[11] = mat[11] * z; 1102 dest[12] = mat[12]; 1103 dest[13] = mat[13]; 1104 dest[14] = mat[14]; 1105 dest[15] = mat[15]; 1106 return dest; 1107 }; 1108 1109 /** 1110 * Rotates a matrix by the given angle around the specified axis 1111 * If rotating around a primary axis (X,Y,Z) one of the specialized rotation functions should be used instead for performance 1112 * 1113 * @param {mat4} mat mat4 to rotate 1114 * @param {number} angle Angle (in radians) to rotate 1115 * @param {vec3} axis vec3 representing the axis to rotate around 1116 * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat 1117 * 1118 * @returns {mat4} dest if specified, mat otherwise 1119 */ 1120 mat4.rotate = function (mat, angle, axis, dest) { 1121 var x = axis[0], y = axis[1], z = axis[2], 1122 len = Math.sqrt(x * x + y * y + z * z), 1123 s, c, t, 1124 a00, a01, a02, a03, 1125 a10, a11, a12, a13, 1126 a20, a21, a22, a23, 1127 b00, b01, b02, 1128 b10, b11, b12, 1129 b20, b21, b22; 1130 1131 if (!len) { return null; } 1132 if (len !== 1) { 1133 len = 1 / len; 1134 x *= len; 1135 y *= len; 1136 z *= len; 1137 } 1138 1139 s = Math.sin(angle); 1140 c = Math.cos(angle); 1141 t = 1 - c; 1142 1143 a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3]; 1144 a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7]; 1145 a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11]; 1146 1147 // Construct the elements of the rotation matrix 1148 b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; 1149 b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; 1150 b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; 1151 1152 if (!dest) { 1153 dest = mat; 1154 } else if (mat !== dest) { // If the source and destination differ, copy the unchanged last row 1155 dest[12] = mat[12]; 1156 dest[13] = mat[13]; 1157 dest[14] = mat[14]; 1158 dest[15] = mat[15]; 1159 } 1160 1161 // Perform rotation-specific matrix multiplication 1162 dest[0] = a00 * b00 + a10 * b01 + a20 * b02; 1163 dest[1] = a01 * b00 + a11 * b01 + a21 * b02; 1164 dest[2] = a02 * b00 + a12 * b01 + a22 * b02; 1165 dest[3] = a03 * b00 + a13 * b01 + a23 * b02; 1166 1167 dest[4] = a00 * b10 + a10 * b11 + a20 * b12; 1168 dest[5] = a01 * b10 + a11 * b11 + a21 * b12; 1169 dest[6] = a02 * b10 + a12 * b11 + a22 * b12; 1170 dest[7] = a03 * b10 + a13 * b11 + a23 * b12; 1171 1172 dest[8] = a00 * b20 + a10 * b21 + a20 * b22; 1173 dest[9] = a01 * b20 + a11 * b21 + a21 * b22; 1174 dest[10] = a02 * b20 + a12 * b21 + a22 * b22; 1175 dest[11] = a03 * b20 + a13 * b21 + a23 * b22; 1176 return dest; 1177 }; 1178 1179 /** 1180 * Rotates a matrix by the given angle around the X axis 1181 * 1182 * @param {mat4} mat mat4 to rotate 1183 * @param {number} angle Angle (in radians) to rotate 1184 * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat 1185 * 1186 * @returns {mat4} dest if specified, mat otherwise 1187 */ 1188 mat4.rotateX = function (mat, angle, dest) { 1189 var s = Math.sin(angle), 1190 c = Math.cos(angle), 1191 a10 = mat[4], 1192 a11 = mat[5], 1193 a12 = mat[6], 1194 a13 = mat[7], 1195 a20 = mat[8], 1196 a21 = mat[9], 1197 a22 = mat[10], 1198 a23 = mat[11]; 1199 1200 if (!dest) { 1201 dest = mat; 1202 } else if (mat !== dest) { // If the source and destination differ, copy the unchanged rows 1203 dest[0] = mat[0]; 1204 dest[1] = mat[1]; 1205 dest[2] = mat[2]; 1206 dest[3] = mat[3]; 1207 1208 dest[12] = mat[12]; 1209 dest[13] = mat[13]; 1210 dest[14] = mat[14]; 1211 dest[15] = mat[15]; 1212 } 1213 1214 // Perform axis-specific matrix multiplication 1215 dest[4] = a10 * c + a20 * s; 1216 dest[5] = a11 * c + a21 * s; 1217 dest[6] = a12 * c + a22 * s; 1218 dest[7] = a13 * c + a23 * s; 1219 1220 dest[8] = a10 * -s + a20 * c; 1221 dest[9] = a11 * -s + a21 * c; 1222 dest[10] = a12 * -s + a22 * c; 1223 dest[11] = a13 * -s + a23 * c; 1224 return dest; 1225 }; 1226 1227 /** 1228 * Rotates a matrix by the given angle around the Y axis 1229 * 1230 * @param {mat4} mat mat4 to rotate 1231 * @param {number} angle Angle (in radians) to rotate 1232 * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat 1233 * 1234 * @returns {mat4} dest if specified, mat otherwise 1235 */ 1236 mat4.rotateY = function (mat, angle, dest) { 1237 var s = Math.sin(angle), 1238 c = Math.cos(angle), 1239 a00 = mat[0], 1240 a01 = mat[1], 1241 a02 = mat[2], 1242 a03 = mat[3], 1243 a20 = mat[8], 1244 a21 = mat[9], 1245 a22 = mat[10], 1246 a23 = mat[11]; 1247 1248 if (!dest) { 1249 dest = mat; 1250 } else if (mat !== dest) { // If the source and destination differ, copy the unchanged rows 1251 dest[4] = mat[4]; 1252 dest[5] = mat[5]; 1253 dest[6] = mat[6]; 1254 dest[7] = mat[7]; 1255 1256 dest[12] = mat[12]; 1257 dest[13] = mat[13]; 1258 dest[14] = mat[14]; 1259 dest[15] = mat[15]; 1260 } 1261 1262 // Perform axis-specific matrix multiplication 1263 dest[0] = a00 * c + a20 * -s; 1264 dest[1] = a01 * c + a21 * -s; 1265 dest[2] = a02 * c + a22 * -s; 1266 dest[3] = a03 * c + a23 * -s; 1267 1268 dest[8] = a00 * s + a20 * c; 1269 dest[9] = a01 * s + a21 * c; 1270 dest[10] = a02 * s + a22 * c; 1271 dest[11] = a03 * s + a23 * c; 1272 return dest; 1273 }; 1274 1275 /** 1276 * Rotates a matrix by the given angle around the Z axis 1277 * 1278 * @param {mat4} mat mat4 to rotate 1279 * @param {number} angle Angle (in radians) to rotate 1280 * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat 1281 * 1282 * @returns {mat4} dest if specified, mat otherwise 1283 */ 1284 mat4.rotateZ = function (mat, angle, dest) { 1285 var s = Math.sin(angle), 1286 c = Math.cos(angle), 1287 a00 = mat[0], 1288 a01 = mat[1], 1289 a02 = mat[2], 1290 a03 = mat[3], 1291 a10 = mat[4], 1292 a11 = mat[5], 1293 a12 = mat[6], 1294 a13 = mat[7]; 1295 1296 if (!dest) { 1297 dest = mat; 1298 } else if (mat !== dest) { // If the source and destination differ, copy the unchanged last row 1299 dest[8] = mat[8]; 1300 dest[9] = mat[9]; 1301 dest[10] = mat[10]; 1302 dest[11] = mat[11]; 1303 1304 dest[12] = mat[12]; 1305 dest[13] = mat[13]; 1306 dest[14] = mat[14]; 1307 dest[15] = mat[15]; 1308 } 1309 1310 // Perform axis-specific matrix multiplication 1311 dest[0] = a00 * c + a10 * s; 1312 dest[1] = a01 * c + a11 * s; 1313 dest[2] = a02 * c + a12 * s; 1314 dest[3] = a03 * c + a13 * s; 1315 1316 dest[4] = a00 * -s + a10 * c; 1317 dest[5] = a01 * -s + a11 * c; 1318 dest[6] = a02 * -s + a12 * c; 1319 dest[7] = a03 * -s + a13 * c; 1320 1321 return dest; 1322 }; 1323 1324 /** 1325 * Generates a frustum matrix with the given bounds 1326 * 1327 * @param {number} left Left bound of the frustum 1328 * @param {number} right Right bound of the frustum 1329 * @param {number} bottom Bottom bound of the frustum 1330 * @param {number} top Top bound of the frustum 1331 * @param {number} near Near bound of the frustum 1332 * @param {number} far Far bound of the frustum 1333 * @param {mat4} [dest] mat4 frustum matrix will be written into 1334 * 1335 * @returns {mat4} dest if specified, a new mat4 otherwise 1336 */ 1337 mat4.frustum = function (left, right, bottom, top, near, far, dest) { 1338 if (!dest) { dest = mat4.create(); } 1339 var rl = (right - left), 1340 tb = (top - bottom), 1341 fn = (far - near); 1342 dest[0] = (near * 2) / rl; 1343 dest[1] = 0; 1344 dest[2] = 0; 1345 dest[3] = 0; 1346 dest[4] = 0; 1347 dest[5] = (near * 2) / tb; 1348 dest[6] = 0; 1349 dest[7] = 0; 1350 dest[8] = (right + left) / rl; 1351 dest[9] = (top + bottom) / tb; 1352 dest[10] = -(far + near) / fn; 1353 dest[11] = -1; 1354 dest[12] = 0; 1355 dest[13] = 0; 1356 dest[14] = -(far * near * 2) / fn; 1357 dest[15] = 0; 1358 return dest; 1359 }; 1360 1361 /** 1362 * Generates a perspective projection matrix with the given bounds 1363 * 1364 * @param {number} fovy Vertical field of view 1365 * @param {number} aspect Aspect ratio. typically viewport width/height 1366 * @param {number} near Near bound of the frustum 1367 * @param {number} far Far bound of the frustum 1368 * @param {mat4} [dest] mat4 frustum matrix will be written into 1369 * 1370 * @returns {mat4} dest if specified, a new mat4 otherwise 1371 */ 1372 mat4.perspective = function (fovy, aspect, near, far, dest) { 1373 var top = near * Math.tan(fovy * Math.PI / 360.0), 1374 right = top * aspect; 1375 return mat4.frustum(-right, right, -top, top, near, far, dest); 1376 }; 1377 1378 /** 1379 * Generates a orthogonal projection matrix with the given bounds 1380 * 1381 * @param {number} left Left bound of the frustum 1382 * @param {number} right Right bound of the frustum 1383 * @param {number} bottom Bottom bound of the frustum 1384 * @param {number} top Top bound of the frustum 1385 * @param {number} near Near bound of the frustum 1386 * @param {number} far Far bound of the frustum 1387 * @param {mat4} [dest] mat4 frustum matrix will be written into 1388 * 1389 * @returns {mat4} dest if specified, a new mat4 otherwise 1390 */ 1391 mat4.ortho = function (left, right, bottom, top, near, far, dest) { 1392 if (!dest) { dest = mat4.create(); } 1393 var rl = (right - left), 1394 tb = (top - bottom), 1395 fn = (far - near); 1396 dest[0] = 2 / rl; 1397 dest[1] = 0; 1398 dest[2] = 0; 1399 dest[3] = 0; 1400 dest[4] = 0; 1401 dest[5] = 2 / tb; 1402 dest[6] = 0; 1403 dest[7] = 0; 1404 dest[8] = 0; 1405 dest[9] = 0; 1406 dest[10] = -2 / fn; 1407 dest[11] = 0; 1408 dest[12] = -(left + right) / rl; 1409 dest[13] = -(top + bottom) / tb; 1410 dest[14] = -(far + near) / fn; 1411 dest[15] = 1; 1412 return dest; 1413 }; 1414 1415 /** 1416 * Generates a look-at matrix with the given eye position, focal point, and up axis 1417 * 1418 * @param {vec3} eye Position of the viewer 1419 * @param {vec3} center Point the viewer is looking at 1420 * @param {vec3} up vec3 pointing "up" 1421 * @param {mat4} [dest] mat4 frustum matrix will be written into 1422 * 1423 * @returns {mat4} dest if specified, a new mat4 otherwise 1424 */ 1425 mat4.lookAt = function (eye, center, up, dest) { 1426 if (!dest) { dest = mat4.create(); } 1427 1428 var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, 1429 eyex = eye[0], 1430 eyey = eye[1], 1431 eyez = eye[2], 1432 upx = up[0], 1433 upy = up[1], 1434 upz = up[2], 1435 centerx = center[0], 1436 centery = center[1], 1437 centerz = center[2]; 1438 1439 if (eyex === centerx && eyey === centery && eyez === centerz) { 1440 return mat4.identity(dest); 1441 } 1442 1443 //vec3.direction(eye, center, z); 1444 z0 = eyex - centerx; 1445 z1 = eyey - centery; 1446 z2 = eyez - centerz; 1447 1448 // normalize (no check needed for 0 because of early return) 1449 len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); 1450 z0 *= len; 1451 z1 *= len; 1452 z2 *= len; 1453 1454 //vec3.normalize(vec3.cross(up, z, x)); 1455 x0 = upy * z2 - upz * z1; 1456 x1 = upz * z0 - upx * z2; 1457 x2 = upx * z1 - upy * z0; 1458 len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); 1459 if (!len) { 1460 x0 = 0; 1461 x1 = 0; 1462 x2 = 0; 1463 } else { 1464 len = 1 / len; 1465 x0 *= len; 1466 x1 *= len; 1467 x2 *= len; 1468 } 1469 1470 //vec3.normalize(vec3.cross(z, x, y)); 1471 y0 = z1 * x2 - z2 * x1; 1472 y1 = z2 * x0 - z0 * x2; 1473 y2 = z0 * x1 - z1 * x0; 1474 1475 len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); 1476 if (!len) { 1477 y0 = 0; 1478 y1 = 0; 1479 y2 = 0; 1480 } else { 1481 len = 1 / len; 1482 y0 *= len; 1483 y1 *= len; 1484 y2 *= len; 1485 } 1486 1487 dest[0] = x0; 1488 dest[1] = y0; 1489 dest[2] = z0; 1490 dest[3] = 0; 1491 dest[4] = x1; 1492 dest[5] = y1; 1493 dest[6] = z1; 1494 dest[7] = 0; 1495 dest[8] = x2; 1496 dest[9] = y2; 1497 dest[10] = z2; 1498 dest[11] = 0; 1499 dest[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); 1500 dest[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); 1501 dest[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); 1502 dest[15] = 1; 1503 1504 return dest; 1505 }; 1506 1507 /** 1508 * Creates a matrix from a quaternion rotation and vector translation 1509 * This is equivalent to (but much faster than): 1510 * 1511 * mat4.identity(dest); 1512 * mat4.translate(dest, vec); 1513 * var quatMat = mat4.create(); 1514 * quat4.toMat4(quat, quatMat); 1515 * mat4.multiply(dest, quatMat); 1516 * 1517 * @param {quat4} quat Rotation quaternion 1518 * @param {vec3} vec Translation vector 1519 * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to a new mat4 1520 * 1521 * @returns {mat4} dest if specified, a new mat4 otherwise 1522 */ 1523 /* mat4.fromRotationTranslation = function (quat, vec, dest) { 1524 if (!dest) { dest = mat4.create(); } 1525 1526 // Quaternion math 1527 var x = quat[0], y = quat[1], z = quat[2], w = quat[3], 1528 x2 = x + x, 1529 y2 = y + y, 1530 z2 = z + z, 1531 1532 xx = x * x2, 1533 xy = x * y2, 1534 xz = x * z2, 1535 yy = y * y2, 1536 yz = y * z2, 1537 zz = z * z2, 1538 wx = w * x2, 1539 wy = w * y2, 1540 wz = w * z2; 1541 1542 dest[0] = 1 - (yy + zz); 1543 dest[1] = xy + wz; 1544 dest[2] = xz - wy; 1545 dest[3] = 0; 1546 dest[4] = xy - wz; 1547 dest[5] = 1 - (xx + zz); 1548 dest[6] = yz + wx; 1549 dest[7] = 0; 1550 dest[8] = xz + wy; 1551 dest[9] = yz - wx; 1552 dest[10] = 1 - (xx + yy); 1553 dest[11] = 0; 1554 dest[12] = vec[0]; 1555 dest[13] = vec[1]; 1556 dest[14] = vec[2]; 1557 dest[15] = 1; 1558 1559 return dest; 1560 };*/ 1561 1562 /** 1563 * Returns a string representation of a mat4 1564 * 1565 * @param {mat4} mat mat4 to represent as a string 1566 * 1567 * @returns {string} String representation of mat 1568 */ 1569 mat4.str = function (mat) { 1570 return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + ', ' + mat[3] + 1571 ', ' + mat[4] + ', ' + mat[5] + ', ' + mat[6] + ', ' + mat[7] + 1572 ', ' + mat[8] + ', ' + mat[9] + ', ' + mat[10] + ', ' + mat[11] + 1573 ', ' + mat[12] + ', ' + mat[13] + ', ' + mat[14] + ', ' + mat[15] + ']'; 1574 }; 1575 1576 /** 1577 * @class Quaternion 1578 * @name quat4 1579 */ 1580 var quat4 = {}; 1581 1582 /** 1583 * Creates a new instance of a quat4 using the default array type 1584 * Any javascript array containing at least 4 numeric elements can serve as a quat4 1585 * 1586 * @param {quat4} [quat] quat4 containing values to initialize with 1587 * 1588 * @returns {quat4} New quat4 1589 */ 1590 quat4.create = function (quat) { 1591 var dest = new MatrixArray(4); 1592 1593 if (quat) { 1594 dest[0] = quat[0]; 1595 dest[1] = quat[1]; 1596 dest[2] = quat[2]; 1597 dest[3] = quat[3]; 1598 } else { 1599 dest[0] = dest[1] = dest[2] = dest[3] = 0; 1600 } 1601 1602 return dest; 1603 }; 1604 1605 /** 1606 * Creates a new instance of a quat4, initializing it with the given arguments 1607 * 1608 * @param {number} x X value 1609 * @param {number} y Y value 1610 * @param {number} z Z value 1611 * @param {number} w W value 1612 1613 * @returns {quat4} New quat4 1614 */ 1615 quat4.createFrom = function (x, y, z, w) { 1616 var dest = new MatrixArray(4); 1617 1618 dest[0] = x; 1619 dest[1] = y; 1620 dest[2] = z; 1621 dest[3] = w; 1622 1623 return dest; 1624 }; 1625 1626 /** 1627 * Copies the values of one quat4 to another 1628 * 1629 * @param {quat4} quat quat4 containing values to copy 1630 * @param {quat4} dest quat4 receiving copied values 1631 * 1632 * @returns {quat4} dest 1633 */ 1634 quat4.set = function (quat, dest) { 1635 dest[0] = quat[0]; 1636 dest[1] = quat[1]; 1637 dest[2] = quat[2]; 1638 dest[3] = quat[3]; 1639 1640 return dest; 1641 }; 1642 1643 /** 1644 * Compares two quaternions for equality within a certain margin of error 1645 * 1646 * @param {quat4} a First vector 1647 * @param {quat4} b Second vector 1648 * 1649 * @returns {Boolean} True if a is equivalent to b 1650 */ 1651 quat4.equal = function (a, b) { 1652 return a === b || ( 1653 Math.abs(a[0] - b[0]) < FLOAT_EPSILON && 1654 Math.abs(a[1] - b[1]) < FLOAT_EPSILON && 1655 Math.abs(a[2] - b[2]) < FLOAT_EPSILON && 1656 Math.abs(a[3] - b[3]) < FLOAT_EPSILON 1657 ); 1658 }; 1659 1660 /** 1661 * Creates a new identity Quat4 1662 * 1663 * @param {quat4} [dest] quat4 receiving copied values 1664 * 1665 * @returns {quat4} dest is specified, new quat4 otherwise 1666 */ 1667 quat4.identity = function (dest) { 1668 if (!dest) { dest = quat4.create(); } 1669 dest[0] = 0; 1670 dest[1] = 0; 1671 dest[2] = 0; 1672 dest[3] = 1; 1673 return dest; 1674 }; 1675 1676 var identityQuat4 = quat4.identity(); 1677 1678 /** 1679 * Calculates the W component of a quat4 from the X, Y, and Z components. 1680 * Assumes that quaternion is 1 unit in length. 1681 * Any existing W component will be ignored. 1682 * 1683 * @param {quat4} quat quat4 to calculate W component of 1684 * @param {quat4} [dest] quat4 receiving calculated values. If not specified result is written to quat 1685 * 1686 * @returns {quat4} dest if specified, quat otherwise 1687 */ 1688 quat4.calculateW = function (quat, dest) { 1689 var x = quat[0], y = quat[1], z = quat[2]; 1690 1691 if (!dest || quat === dest) { 1692 quat[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); 1693 return quat; 1694 } 1695 dest[0] = x; 1696 dest[1] = y; 1697 dest[2] = z; 1698 dest[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); 1699 return dest; 1700 }; 1701 1702 /** 1703 * Calculates the dot product of two quaternions 1704 * 1705 * @param {quat4} quat First operand 1706 * @param {quat4} quat2 Second operand 1707 * 1708 * @return {number} Dot product of quat and quat2 1709 */ 1710 quat4.dot = function(quat, quat2){ 1711 return quat[0]*quat2[0] + quat[1]*quat2[1] + quat[2]*quat2[2] + quat[3]*quat2[3]; 1712 }; 1713 1714 /** 1715 * Calculates the inverse of a quat4 1716 * 1717 * @param {quat4} quat quat4 to calculate inverse of 1718 * @param {quat4} [dest] quat4 receiving inverse values. If not specified result is written to quat 1719 * 1720 * @returns {quat4} dest if specified, quat otherwise 1721 */ 1722 quat4.inverse = function(quat, dest) { 1723 var q0 = quat[0], q1 = quat[1], q2 = quat[2], q3 = quat[3], 1724 dot = q0*q0 + q1*q1 + q2*q2 + q3*q3, 1725 invDot = dot ? 1.0/dot : 0; 1726 1727 // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 1728 1729 if(!dest || quat === dest) { 1730 quat[0] *= -invDot; 1731 quat[1] *= -invDot; 1732 quat[2] *= -invDot; 1733 quat[3] *= invDot; 1734 return quat; 1735 } 1736 dest[0] = -quat[0]*invDot; 1737 dest[1] = -quat[1]*invDot; 1738 dest[2] = -quat[2]*invDot; 1739 dest[3] = quat[3]*invDot; 1740 return dest; 1741 }; 1742 1743 1744 /** 1745 * Calculates the conjugate of a quat4 1746 * If the quaternion is normalized, this function is faster than quat4.inverse and produces the same result. 1747 * 1748 * @param {quat4} quat quat4 to calculate conjugate of 1749 * @param {quat4} [dest] quat4 receiving conjugate values. If not specified result is written to quat 1750 * 1751 * @returns {quat4} dest if specified, quat otherwise 1752 */ 1753 quat4.conjugate = function (quat, dest) { 1754 if (!dest || quat === dest) { 1755 quat[0] *= -1; 1756 quat[1] *= -1; 1757 quat[2] *= -1; 1758 return quat; 1759 } 1760 dest[0] = -quat[0]; 1761 dest[1] = -quat[1]; 1762 dest[2] = -quat[2]; 1763 dest[3] = quat[3]; 1764 return dest; 1765 }; 1766 1767 /** 1768 * Calculates the length of a quat4 1769 * 1770 * Params: 1771 * @param {quat4} quat quat4 to calculate length of 1772 * 1773 * @returns Length of quat 1774 */ 1775 quat4.length = function (quat) { 1776 var x = quat[0], y = quat[1], z = quat[2], w = quat[3]; 1777 return Math.sqrt(x * x + y * y + z * z + w * w); 1778 }; 1779 1780 /** 1781 * Generates a unit quaternion of the same direction as the provided quat4 1782 * If quaternion length is 0, returns [0, 0, 0, 0] 1783 * 1784 * @param {quat4} quat quat4 to normalize 1785 * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat 1786 * 1787 * @returns {quat4} dest if specified, quat otherwise 1788 */ 1789 quat4.normalize = function (quat, dest) { 1790 if (!dest) { dest = quat; } 1791 1792 var x = quat[0], y = quat[1], z = quat[2], w = quat[3], 1793 len = Math.sqrt(x * x + y * y + z * z + w * w); 1794 if (len === 0) { 1795 dest[0] = 0; 1796 dest[1] = 0; 1797 dest[2] = 0; 1798 dest[3] = 0; 1799 return dest; 1800 } 1801 len = 1 / len; 1802 dest[0] = x * len; 1803 dest[1] = y * len; 1804 dest[2] = z * len; 1805 dest[3] = w * len; 1806 1807 return dest; 1808 }; 1809 1810 /** 1811 * Performs quaternion addition 1812 * 1813 * @param {quat4} quat First operand 1814 * @param {quat4} quat2 Second operand 1815 * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat 1816 * 1817 * @returns {quat4} dest if specified, quat otherwise 1818 */ 1819 quat4.add = function (quat, quat2, dest) { 1820 if(!dest || quat === dest) { 1821 quat[0] += quat2[0]; 1822 quat[1] += quat2[1]; 1823 quat[2] += quat2[2]; 1824 quat[3] += quat2[3]; 1825 return quat; 1826 } 1827 dest[0] = quat[0]+quat2[0]; 1828 dest[1] = quat[1]+quat2[1]; 1829 dest[2] = quat[2]+quat2[2]; 1830 dest[3] = quat[3]+quat2[3]; 1831 return dest; 1832 }; 1833 1834 /** 1835 * Performs a quaternion multiplication 1836 * 1837 * @param {quat4} quat First operand 1838 * @param {quat4} quat2 Second operand 1839 * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat 1840 * 1841 * @returns {quat4} dest if specified, quat otherwise 1842 */ 1843 quat4.multiply = function (quat, quat2, dest) { 1844 if (!dest) { dest = quat; } 1845 1846 var qax = quat[0], qay = quat[1], qaz = quat[2], qaw = quat[3], 1847 qbx = quat2[0], qby = quat2[1], qbz = quat2[2], qbw = quat2[3]; 1848 1849 dest[0] = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; 1850 dest[1] = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; 1851 dest[2] = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; 1852 dest[3] = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; 1853 1854 return dest; 1855 }; 1856 1857 /** 1858 * Transforms a vec3 with the given quaternion 1859 * 1860 * @param {quat4} quat quat4 to transform the vector with 1861 * @param {vec3} vec vec3 to transform 1862 * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec 1863 * 1864 * @returns dest if specified, vec otherwise 1865 */ 1866 quat4.multiplyVec3 = function (quat, vec, dest) { 1867 if (!dest) { dest = vec; } 1868 1869 var x = vec[0], y = vec[1], z = vec[2], 1870 qx = quat[0], qy = quat[1], qz = quat[2], qw = quat[3], 1871 1872 // calculate quat * vec 1873 ix = qw * x + qy * z - qz * y, 1874 iy = qw * y + qz * x - qx * z, 1875 iz = qw * z + qx * y - qy * x, 1876 iw = -qx * x - qy * y - qz * z; 1877 1878 // calculate result * inverse quat 1879 dest[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; 1880 dest[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; 1881 dest[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; 1882 1883 return dest; 1884 }; 1885 1886 /** 1887 * Multiplies the components of a quaternion by a scalar value 1888 * 1889 * @param {quat4} quat to scale 1890 * @param {number} val Value to scale by 1891 * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat 1892 * 1893 * @returns {quat4} dest if specified, quat otherwise 1894 */ 1895 quat4.scale = function (quat, val, dest) { 1896 if(!dest || quat === dest) { 1897 quat[0] *= val; 1898 quat[1] *= val; 1899 quat[2] *= val; 1900 quat[3] *= val; 1901 return quat; 1902 } 1903 dest[0] = quat[0]*val; 1904 dest[1] = quat[1]*val; 1905 dest[2] = quat[2]*val; 1906 dest[3] = quat[3]*val; 1907 return dest; 1908 }; 1909 1910 /** 1911 * Calculates a 4x4 matrix from the given quat4 1912 * 1913 * @param {quat4} quat quat4 to create matrix from 1914 * @param {mat4} [dest] mat4 receiving operation result 1915 * 1916 * @returns {mat4} dest if specified, a new mat4 otherwise 1917 */ 1918 quat4.toMat4 = function (quat, dest) { 1919 if (!dest) { dest = mat4.create(); } 1920 1921 var x = quat[0], y = quat[1], z = quat[2], w = quat[3], 1922 x2 = x + x, 1923 y2 = y + y, 1924 z2 = z + z, 1925 1926 xx = x * x2, 1927 xy = x * y2, 1928 xz = x * z2, 1929 yy = y * y2, 1930 yz = y * z2, 1931 zz = z * z2, 1932 wx = w * x2, 1933 wy = w * y2, 1934 wz = w * z2; 1935 1936 dest[0] = 1 - (yy + zz); 1937 dest[1] = xy + wz; 1938 dest[2] = xz - wy; 1939 dest[3] = 0; 1940 1941 dest[4] = xy - wz; 1942 dest[5] = 1 - (xx + zz); 1943 dest[6] = yz + wx; 1944 dest[7] = 0; 1945 1946 dest[8] = xz + wy; 1947 dest[9] = yz - wx; 1948 dest[10] = 1 - (xx + yy); 1949 dest[11] = 0; 1950 1951 dest[12] = 0; 1952 dest[13] = 0; 1953 dest[14] = 0; 1954 dest[15] = 1; 1955 1956 return dest; 1957 }; 1958 1959 /** 1960 * Performs a spherical linear interpolation between two quat4 1961 * 1962 * @param {quat4} quat First quaternion 1963 * @param {quat4} quat2 Second quaternion 1964 * @param {number} slerp Interpolation amount between the two inputs 1965 * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat 1966 * 1967 * @returns {quat4} dest if specified, quat otherwise 1968 */ 1969 quat4.slerp = function (quat, quat2, slerp, dest) { 1970 if (!dest) { dest = quat; } 1971 1972 var cosHalfTheta = quat[0] * quat2[0] + quat[1] * quat2[1] + quat[2] * quat2[2] + quat[3] * quat2[3], 1973 halfTheta, 1974 sinHalfTheta, 1975 ratioA, 1976 ratioB; 1977 1978 if (Math.abs(cosHalfTheta) >= 1.0) { 1979 if (dest !== quat) { 1980 dest[0] = quat[0]; 1981 dest[1] = quat[1]; 1982 dest[2] = quat[2]; 1983 dest[3] = quat[3]; 1984 } 1985 return dest; 1986 } 1987 1988 halfTheta = Math.acos(cosHalfTheta); 1989 sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta); 1990 1991 if (Math.abs(sinHalfTheta) < 0.001) { 1992 dest[0] = (quat[0] * 0.5 + quat2[0] * 0.5); 1993 dest[1] = (quat[1] * 0.5 + quat2[1] * 0.5); 1994 dest[2] = (quat[2] * 0.5 + quat2[2] * 0.5); 1995 dest[3] = (quat[3] * 0.5 + quat2[3] * 0.5); 1996 return dest; 1997 } 1998 1999 ratioA = Math.sin((1 - slerp) * halfTheta) / sinHalfTheta; 2000 ratioB = Math.sin(slerp * halfTheta) / sinHalfTheta; 2001 2002 dest[0] = (quat[0] * ratioA + quat2[0] * ratioB); 2003 dest[1] = (quat[1] * ratioA + quat2[1] * ratioB); 2004 dest[2] = (quat[2] * ratioA + quat2[2] * ratioB); 2005 dest[3] = (quat[3] * ratioA + quat2[3] * ratioB); 2006 2007 return dest; 2008 }; 2009 2010 /** 2011 * Creates a quaternion from the given 3x3 rotation matrix. 2012 * If dest is omitted, a new quaternion will be created. 2013 * 2014 * @param {mat3} mat the rotation matrix 2015 * @param {quat4} [dest] an optional receiving quaternion 2016 * 2017 * @returns {quat4} the quaternion constructed from the rotation matrix 2018 * 2019 */ 2020 quat4.fromRotationMatrix = function(mat, dest) { 2021 if (!dest) dest = quat4.create(); 2022 2023 // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes 2024 // article "Quaternion Calculus and Fast Animation". 2025 2026 var fTrace = mat[0] + mat[4] + mat[8]; 2027 var fRoot; 2028 2029 if ( fTrace > 0.0 ) { 2030 // |w| > 1/2, may as well choose w > 1/2 2031 fRoot = Math.sqrt(fTrace + 1.0); // 2w 2032 dest[3] = 0.5 * fRoot; 2033 fRoot = 0.5/fRoot; // 1/(4w) 2034 dest[0] = (mat[7]-mat[5])*fRoot; 2035 dest[1] = (mat[2]-mat[6])*fRoot; 2036 dest[2] = (mat[3]-mat[1])*fRoot; 2037 } else { 2038 // |w| <= 1/2 2039 var s_iNext = quat4.fromRotationMatrix.s_iNext = quat4.fromRotationMatrix.s_iNext || [1,2,0]; 2040 var i = 0; 2041 if ( mat[4] > mat[0] ) 2042 i = 1; 2043 if ( mat[8] > mat[i*3+i] ) 2044 i = 2; 2045 var j = s_iNext[i]; 2046 var k = s_iNext[j]; 2047 2048 fRoot = Math.sqrt(mat[i*3+i]-mat[j*3+j]-mat[k*3+k] + 1.0); 2049 dest[i] = 0.5 * fRoot; 2050 fRoot = 0.5 / fRoot; 2051 dest[3] = (mat[k*3+j] - mat[j*3+k]) * fRoot; 2052 dest[j] = (mat[j*3+i] + mat[i*3+j]) * fRoot; 2053 dest[k] = (mat[k*3+i] + mat[i*3+k]) * fRoot; 2054 } 2055 2056 return dest; 2057 }; 2058 2059 2060 /** 2061 * Sets a quat4 to the Identity and returns it. 2062 * 2063 * @param {quat4} [dest] quat4 to set. If omitted, a 2064 * new quat4 will be created. 2065 * 2066 * @returns {quat4} dest 2067 */ 2068 quat4.identity = function(dest) { 2069 if (!dest) dest = quat4.create(); 2070 dest[0] = 0; 2071 dest[1] = 0; 2072 dest[2] = 0; 2073 dest[3] = 1; 2074 return dest; 2075 }; 2076 2077 /** 2078 * Sets a quat4 from the given angle and rotation axis, 2079 * then returns it. If dest is not given, a new quat4 is created. 2080 * 2081 * @param {Number} angle the angle in radians 2082 * @param {vec3} axis the axis around which to rotate 2083 * @param {quat4} [dest] the optional quat4 to store the result 2084 * 2085 * @returns {quat4} dest 2086 **/ 2087 quat4.fromAngleAxis = function(angle, axis, dest) { 2088 // The quaternion representing the rotation is 2089 // q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k) 2090 if (!dest) dest = quat4.create(); 2091 2092 var half = angle * 0.5; 2093 var s = Math.sin(half); 2094 dest[3] = Math.cos(half); 2095 dest[0] = s * axis[0]; 2096 dest[1] = s * axis[1]; 2097 dest[2] = s * axis[2]; 2098 2099 return dest; 2100 }; 2101 2102 /** 2103 * Stores the angle and axis in a vec4, where the XYZ components represent 2104 * the axis and the W (4th) component is the angle in radians. 2105 * 2106 * If dest is not given, src will be modified in place and returned, after 2107 * which it should not be considered not a quaternion (just an axis and angle). 2108 * 2109 * @param {quat4} quat the quaternion whose angle and axis to store 2110 * @param {vec4} [dest] the optional vec4 to receive the data 2111 * 2112 * @returns {vec4} dest 2113 */ 2114 quat4.toAngleAxis = function(src, dest) { 2115 if (!dest) dest = src; 2116 // The quaternion representing the rotation is 2117 // q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k) 2118 2119 var sqrlen = src[0]*src[0]+src[1]*src[1]+src[2]*src[2]; 2120 if (sqrlen > 0) 2121 { 2122 dest[3] = 2 * Math.acos(src[3]); 2123 var invlen = 1.0 / Math.sqrt(sqrlen); 2124 dest[0] = src[0]*invlen; 2125 dest[1] = src[1]*invlen; 2126 dest[2] = src[2]*invlen; 2127 } else { 2128 // angle is 0 (mod 2*pi), so any axis will do 2129 dest[3] = 0; 2130 dest[0] = 1; 2131 dest[1] = 0; 2132 dest[2] = 0; 2133 } 2134 2135 return dest; 2136 }; 2137 2138 /** 2139 * Returns a string representation of a quaternion 2140 * 2141 * @param {quat4} quat quat4 to represent as a string 2142 * 2143 * @returns {string} String representation of quat 2144 */ 2145 quat4.str = function (quat) { 2146 return '[' + quat[0] + ', ' + quat[1] + ', ' + quat[2] + ', ' + quat[3] + ']'; 2147 }; 2148 2149 2150 /* 2151 * Exports 2152 */ 2153 2154 root.vec3 = vec3; 2155 root.mat4 = mat4; 2156 root.quat4 = quat4; 2157 2158 })(window); 2159