1/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 2 3Redistribution and use in source and binary forms, with or without modification, 4are permitted provided that the following conditions are met: 5 6 * Redistributions of source code must retain the above copyright notice, this 7 list of conditions and the following disclaimer. 8 * Redistributions in binary form must reproduce the above copyright notice, 9 this list of conditions and the following disclaimer in the documentation 10 and/or other materials provided with the distribution. 11 12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 22 23/** 24 * @class 4x4 Matrix 25 * @name mat4 26 */ 27var mat4 = {}; 28 29/** 30 * Creates a new identity mat4 31 * 32 * @returns {mat4} a new 4x4 matrix 33 */ 34mat4.create = function() { 35 var out = new GLMAT_ARRAY_TYPE(16); 36 out[0] = 1; 37 out[1] = 0; 38 out[2] = 0; 39 out[3] = 0; 40 out[4] = 0; 41 out[5] = 1; 42 out[6] = 0; 43 out[7] = 0; 44 out[8] = 0; 45 out[9] = 0; 46 out[10] = 1; 47 out[11] = 0; 48 out[12] = 0; 49 out[13] = 0; 50 out[14] = 0; 51 out[15] = 1; 52 return out; 53}; 54 55/** 56 * Creates a new mat4 initialized with values from an existing matrix 57 * 58 * @param {mat4} a matrix to clone 59 * @returns {mat4} a new 4x4 matrix 60 */ 61mat4.clone = function(a) { 62 var out = new GLMAT_ARRAY_TYPE(16); 63 out[0] = a[0]; 64 out[1] = a[1]; 65 out[2] = a[2]; 66 out[3] = a[3]; 67 out[4] = a[4]; 68 out[5] = a[5]; 69 out[6] = a[6]; 70 out[7] = a[7]; 71 out[8] = a[8]; 72 out[9] = a[9]; 73 out[10] = a[10]; 74 out[11] = a[11]; 75 out[12] = a[12]; 76 out[13] = a[13]; 77 out[14] = a[14]; 78 out[15] = a[15]; 79 return out; 80}; 81 82/** 83 * Copy the values from one mat4 to another 84 * 85 * @param {mat4} out the receiving matrix 86 * @param {mat4} a the source matrix 87 * @returns {mat4} out 88 */ 89mat4.copy = function(out, a) { 90 out[0] = a[0]; 91 out[1] = a[1]; 92 out[2] = a[2]; 93 out[3] = a[3]; 94 out[4] = a[4]; 95 out[5] = a[5]; 96 out[6] = a[6]; 97 out[7] = a[7]; 98 out[8] = a[8]; 99 out[9] = a[9]; 100 out[10] = a[10]; 101 out[11] = a[11]; 102 out[12] = a[12]; 103 out[13] = a[13]; 104 out[14] = a[14]; 105 out[15] = a[15]; 106 return out; 107}; 108 109/** 110 * Set a mat4 to the identity matrix 111 * 112 * @param {mat4} out the receiving matrix 113 * @returns {mat4} out 114 */ 115mat4.identity = function(out) { 116 out[0] = 1; 117 out[1] = 0; 118 out[2] = 0; 119 out[3] = 0; 120 out[4] = 0; 121 out[5] = 1; 122 out[6] = 0; 123 out[7] = 0; 124 out[8] = 0; 125 out[9] = 0; 126 out[10] = 1; 127 out[11] = 0; 128 out[12] = 0; 129 out[13] = 0; 130 out[14] = 0; 131 out[15] = 1; 132 return out; 133}; 134 135/** 136 * Transpose the values of a mat4 137 * 138 * @param {mat4} out the receiving matrix 139 * @param {mat4} a the source matrix 140 * @returns {mat4} out 141 */ 142mat4.transpose = function(out, a) { 143 // If we are transposing ourselves we can skip a few steps but have to cache some values 144 if (out === a) { 145 var a01 = a[1], a02 = a[2], a03 = a[3], 146 a12 = a[6], a13 = a[7], 147 a23 = a[11]; 148 149 out[1] = a[4]; 150 out[2] = a[8]; 151 out[3] = a[12]; 152 out[4] = a01; 153 out[6] = a[9]; 154 out[7] = a[13]; 155 out[8] = a02; 156 out[9] = a12; 157 out[11] = a[14]; 158 out[12] = a03; 159 out[13] = a13; 160 out[14] = a23; 161 } else { 162 out[0] = a[0]; 163 out[1] = a[4]; 164 out[2] = a[8]; 165 out[3] = a[12]; 166 out[4] = a[1]; 167 out[5] = a[5]; 168 out[6] = a[9]; 169 out[7] = a[13]; 170 out[8] = a[2]; 171 out[9] = a[6]; 172 out[10] = a[10]; 173 out[11] = a[14]; 174 out[12] = a[3]; 175 out[13] = a[7]; 176 out[14] = a[11]; 177 out[15] = a[15]; 178 } 179 180 return out; 181}; 182 183/** 184 * Inverts a mat4 185 * 186 * @param {mat4} out the receiving matrix 187 * @param {mat4} a the source matrix 188 * @returns {mat4} out 189 */ 190mat4.invert = function(out, a) { 191 var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], 192 a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], 193 a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], 194 a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], 195 196 b00 = a00 * a11 - a01 * a10, 197 b01 = a00 * a12 - a02 * a10, 198 b02 = a00 * a13 - a03 * a10, 199 b03 = a01 * a12 - a02 * a11, 200 b04 = a01 * a13 - a03 * a11, 201 b05 = a02 * a13 - a03 * a12, 202 b06 = a20 * a31 - a21 * a30, 203 b07 = a20 * a32 - a22 * a30, 204 b08 = a20 * a33 - a23 * a30, 205 b09 = a21 * a32 - a22 * a31, 206 b10 = a21 * a33 - a23 * a31, 207 b11 = a22 * a33 - a23 * a32, 208 209 // Calculate the determinant 210 det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 211 212 if (!det) { 213 return null; 214 } 215 det = 1.0 / det; 216 217 out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; 218 out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; 219 out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; 220 out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; 221 out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; 222 out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; 223 out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; 224 out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; 225 out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; 226 out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; 227 out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; 228 out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; 229 out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; 230 out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; 231 out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; 232 out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; 233 234 return out; 235}; 236 237/** 238 * Calculates the adjugate of a mat4 239 * 240 * @param {mat4} out the receiving matrix 241 * @param {mat4} a the source matrix 242 * @returns {mat4} out 243 */ 244mat4.adjoint = function(out, a) { 245 var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], 246 a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], 247 a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], 248 a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; 249 250 out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); 251 out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); 252 out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); 253 out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); 254 out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); 255 out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); 256 out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); 257 out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); 258 out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); 259 out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); 260 out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); 261 out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); 262 out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); 263 out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); 264 out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); 265 out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); 266 return out; 267}; 268 269/** 270 * Calculates the determinant of a mat4 271 * 272 * @param {mat4} a the source matrix 273 * @returns {Number} determinant of a 274 */ 275mat4.determinant = function (a) { 276 var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], 277 a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], 278 a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], 279 a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], 280 281 b00 = a00 * a11 - a01 * a10, 282 b01 = a00 * a12 - a02 * a10, 283 b02 = a00 * a13 - a03 * a10, 284 b03 = a01 * a12 - a02 * a11, 285 b04 = a01 * a13 - a03 * a11, 286 b05 = a02 * a13 - a03 * a12, 287 b06 = a20 * a31 - a21 * a30, 288 b07 = a20 * a32 - a22 * a30, 289 b08 = a20 * a33 - a23 * a30, 290 b09 = a21 * a32 - a22 * a31, 291 b10 = a21 * a33 - a23 * a31, 292 b11 = a22 * a33 - a23 * a32; 293 294 // Calculate the determinant 295 return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 296}; 297 298/** 299 * Multiplies two mat4's 300 * 301 * @param {mat4} out the receiving matrix 302 * @param {mat4} a the first operand 303 * @param {mat4} b the second operand 304 * @returns {mat4} out 305 */ 306mat4.multiply = function (out, a, b) { 307 var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], 308 a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], 309 a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], 310 a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; 311 312 // Cache only the current line of the second matrix 313 var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; 314 out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 315 out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 316 out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 317 out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 318 319 b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; 320 out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 321 out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 322 out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 323 out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 324 325 b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; 326 out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 327 out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 328 out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 329 out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 330 331 b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; 332 out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; 333 out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; 334 out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; 335 out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; 336 return out; 337}; 338 339/** 340 * Alias for {@link mat4.multiply} 341 * @function 342 */ 343mat4.mul = mat4.multiply; 344 345/** 346 * Translate a mat4 by the given vector 347 * 348 * @param {mat4} out the receiving matrix 349 * @param {mat4} a the matrix to translate 350 * @param {vec3} v vector to translate by 351 * @returns {mat4} out 352 */ 353mat4.translate = function (out, a, v) { 354 var x = v[0], y = v[1], z = v[2], 355 a00, a01, a02, a03, 356 a10, a11, a12, a13, 357 a20, a21, a22, a23; 358 359 if (a === out) { 360 out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; 361 out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; 362 out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; 363 out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; 364 } else { 365 a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; 366 a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; 367 a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; 368 369 out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; 370 out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; 371 out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; 372 373 out[12] = a00 * x + a10 * y + a20 * z + a[12]; 374 out[13] = a01 * x + a11 * y + a21 * z + a[13]; 375 out[14] = a02 * x + a12 * y + a22 * z + a[14]; 376 out[15] = a03 * x + a13 * y + a23 * z + a[15]; 377 } 378 379 return out; 380}; 381 382/** 383 * Scales the mat4 by the dimensions in the given vec3 384 * 385 * @param {mat4} out the receiving matrix 386 * @param {mat4} a the matrix to scale 387 * @param {vec3} v the vec3 to scale the matrix by 388 * @returns {mat4} out 389 **/ 390mat4.scale = function(out, a, v) { 391 var x = v[0], y = v[1], z = v[2]; 392 393 out[0] = a[0] * x; 394 out[1] = a[1] * x; 395 out[2] = a[2] * x; 396 out[3] = a[3] * x; 397 out[4] = a[4] * y; 398 out[5] = a[5] * y; 399 out[6] = a[6] * y; 400 out[7] = a[7] * y; 401 out[8] = a[8] * z; 402 out[9] = a[9] * z; 403 out[10] = a[10] * z; 404 out[11] = a[11] * z; 405 out[12] = a[12]; 406 out[13] = a[13]; 407 out[14] = a[14]; 408 out[15] = a[15]; 409 return out; 410}; 411 412/** 413 * Rotates a mat4 by the given angle 414 * 415 * @param {mat4} out the receiving matrix 416 * @param {mat4} a the matrix to rotate 417 * @param {Number} rad the angle to rotate the matrix by 418 * @param {vec3} axis the axis to rotate around 419 * @returns {mat4} out 420 */ 421mat4.rotate = function (out, a, rad, axis) { 422 var x = axis[0], y = axis[1], z = axis[2], 423 len = Math.sqrt(x * x + y * y + z * z), 424 s, c, t, 425 a00, a01, a02, a03, 426 a10, a11, a12, a13, 427 a20, a21, a22, a23, 428 b00, b01, b02, 429 b10, b11, b12, 430 b20, b21, b22; 431 432 if (Math.abs(len) < GLMAT_EPSILON) { return null; } 433 434 len = 1 / len; 435 x *= len; 436 y *= len; 437 z *= len; 438 439 s = Math.sin(rad); 440 c = Math.cos(rad); 441 t = 1 - c; 442 443 a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; 444 a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; 445 a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; 446 447 // Construct the elements of the rotation matrix 448 b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; 449 b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; 450 b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; 451 452 // Perform rotation-specific matrix multiplication 453 out[0] = a00 * b00 + a10 * b01 + a20 * b02; 454 out[1] = a01 * b00 + a11 * b01 + a21 * b02; 455 out[2] = a02 * b00 + a12 * b01 + a22 * b02; 456 out[3] = a03 * b00 + a13 * b01 + a23 * b02; 457 out[4] = a00 * b10 + a10 * b11 + a20 * b12; 458 out[5] = a01 * b10 + a11 * b11 + a21 * b12; 459 out[6] = a02 * b10 + a12 * b11 + a22 * b12; 460 out[7] = a03 * b10 + a13 * b11 + a23 * b12; 461 out[8] = a00 * b20 + a10 * b21 + a20 * b22; 462 out[9] = a01 * b20 + a11 * b21 + a21 * b22; 463 out[10] = a02 * b20 + a12 * b21 + a22 * b22; 464 out[11] = a03 * b20 + a13 * b21 + a23 * b22; 465 466 if (a !== out) { // If the source and destination differ, copy the unchanged last row 467 out[12] = a[12]; 468 out[13] = a[13]; 469 out[14] = a[14]; 470 out[15] = a[15]; 471 } 472 return out; 473}; 474 475/** 476 * Rotates a matrix by the given angle around the X axis 477 * 478 * @param {mat4} out the receiving matrix 479 * @param {mat4} a the matrix to rotate 480 * @param {Number} rad the angle to rotate the matrix by 481 * @returns {mat4} out 482 */ 483mat4.rotateX = function (out, a, rad) { 484 var s = Math.sin(rad), 485 c = Math.cos(rad), 486 a10 = a[4], 487 a11 = a[5], 488 a12 = a[6], 489 a13 = a[7], 490 a20 = a[8], 491 a21 = a[9], 492 a22 = a[10], 493 a23 = a[11]; 494 495 if (a !== out) { // If the source and destination differ, copy the unchanged rows 496 out[0] = a[0]; 497 out[1] = a[1]; 498 out[2] = a[2]; 499 out[3] = a[3]; 500 out[12] = a[12]; 501 out[13] = a[13]; 502 out[14] = a[14]; 503 out[15] = a[15]; 504 } 505 506 // Perform axis-specific matrix multiplication 507 out[4] = a10 * c + a20 * s; 508 out[5] = a11 * c + a21 * s; 509 out[6] = a12 * c + a22 * s; 510 out[7] = a13 * c + a23 * s; 511 out[8] = a20 * c - a10 * s; 512 out[9] = a21 * c - a11 * s; 513 out[10] = a22 * c - a12 * s; 514 out[11] = a23 * c - a13 * s; 515 return out; 516}; 517 518/** 519 * Rotates a matrix by the given angle around the Y axis 520 * 521 * @param {mat4} out the receiving matrix 522 * @param {mat4} a the matrix to rotate 523 * @param {Number} rad the angle to rotate the matrix by 524 * @returns {mat4} out 525 */ 526mat4.rotateY = function (out, a, rad) { 527 var s = Math.sin(rad), 528 c = Math.cos(rad), 529 a00 = a[0], 530 a01 = a[1], 531 a02 = a[2], 532 a03 = a[3], 533 a20 = a[8], 534 a21 = a[9], 535 a22 = a[10], 536 a23 = a[11]; 537 538 if (a !== out) { // If the source and destination differ, copy the unchanged rows 539 out[4] = a[4]; 540 out[5] = a[5]; 541 out[6] = a[6]; 542 out[7] = a[7]; 543 out[12] = a[12]; 544 out[13] = a[13]; 545 out[14] = a[14]; 546 out[15] = a[15]; 547 } 548 549 // Perform axis-specific matrix multiplication 550 out[0] = a00 * c - a20 * s; 551 out[1] = a01 * c - a21 * s; 552 out[2] = a02 * c - a22 * s; 553 out[3] = a03 * c - a23 * s; 554 out[8] = a00 * s + a20 * c; 555 out[9] = a01 * s + a21 * c; 556 out[10] = a02 * s + a22 * c; 557 out[11] = a03 * s + a23 * c; 558 return out; 559}; 560 561/** 562 * Rotates a matrix by the given angle around the Z axis 563 * 564 * @param {mat4} out the receiving matrix 565 * @param {mat4} a the matrix to rotate 566 * @param {Number} rad the angle to rotate the matrix by 567 * @returns {mat4} out 568 */ 569mat4.rotateZ = function (out, a, rad) { 570 var s = Math.sin(rad), 571 c = Math.cos(rad), 572 a00 = a[0], 573 a01 = a[1], 574 a02 = a[2], 575 a03 = a[3], 576 a10 = a[4], 577 a11 = a[5], 578 a12 = a[6], 579 a13 = a[7]; 580 581 if (a !== out) { // If the source and destination differ, copy the unchanged last row 582 out[8] = a[8]; 583 out[9] = a[9]; 584 out[10] = a[10]; 585 out[11] = a[11]; 586 out[12] = a[12]; 587 out[13] = a[13]; 588 out[14] = a[14]; 589 out[15] = a[15]; 590 } 591 592 // Perform axis-specific matrix multiplication 593 out[0] = a00 * c + a10 * s; 594 out[1] = a01 * c + a11 * s; 595 out[2] = a02 * c + a12 * s; 596 out[3] = a03 * c + a13 * s; 597 out[4] = a10 * c - a00 * s; 598 out[5] = a11 * c - a01 * s; 599 out[6] = a12 * c - a02 * s; 600 out[7] = a13 * c - a03 * s; 601 return out; 602}; 603 604/** 605 * Creates a matrix from a quaternion rotation and vector translation 606 * This is equivalent to (but much faster than): 607 * 608 * mat4.identity(dest); 609 * mat4.translate(dest, vec); 610 * var quatMat = mat4.create(); 611 * quat4.toMat4(quat, quatMat); 612 * mat4.multiply(dest, quatMat); 613 * 614 * @param {mat4} out mat4 receiving operation result 615 * @param {quat4} q Rotation quaternion 616 * @param {vec3} v Translation vector 617 * @returns {mat4} out 618 */ 619mat4.fromRotationTranslation = function (out, q, v) { 620 // Quaternion math 621 var x = q[0], y = q[1], z = q[2], w = q[3], 622 x2 = x + x, 623 y2 = y + y, 624 z2 = z + z, 625 626 xx = x * x2, 627 xy = x * y2, 628 xz = x * z2, 629 yy = y * y2, 630 yz = y * z2, 631 zz = z * z2, 632 wx = w * x2, 633 wy = w * y2, 634 wz = w * z2; 635 636 out[0] = 1 - (yy + zz); 637 out[1] = xy + wz; 638 out[2] = xz - wy; 639 out[3] = 0; 640 out[4] = xy - wz; 641 out[5] = 1 - (xx + zz); 642 out[6] = yz + wx; 643 out[7] = 0; 644 out[8] = xz + wy; 645 out[9] = yz - wx; 646 out[10] = 1 - (xx + yy); 647 out[11] = 0; 648 out[12] = v[0]; 649 out[13] = v[1]; 650 out[14] = v[2]; 651 out[15] = 1; 652 653 return out; 654}; 655 656/** 657* Calculates a 4x4 matrix from the given quaternion 658* 659* @param {mat4} out mat4 receiving operation result 660* @param {quat} q Quaternion to create matrix from 661* 662* @returns {mat4} out 663*/ 664mat4.fromQuat = function (out, q) { 665 var x = q[0], y = q[1], z = q[2], w = q[3], 666 x2 = x + x, 667 y2 = y + y, 668 z2 = z + z, 669 670 xx = x * x2, 671 xy = x * y2, 672 xz = x * z2, 673 yy = y * y2, 674 yz = y * z2, 675 zz = z * z2, 676 wx = w * x2, 677 wy = w * y2, 678 wz = w * z2; 679 680 out[0] = 1 - (yy + zz); 681 out[1] = xy + wz; 682 out[2] = xz - wy; 683 out[3] = 0; 684 685 out[4] = xy - wz; 686 out[5] = 1 - (xx + zz); 687 out[6] = yz + wx; 688 out[7] = 0; 689 690 out[8] = xz + wy; 691 out[9] = yz - wx; 692 out[10] = 1 - (xx + yy); 693 out[11] = 0; 694 695 out[12] = 0; 696 out[13] = 0; 697 out[14] = 0; 698 out[15] = 1; 699 700 return out; 701}; 702 703/** 704 * Generates a frustum matrix with the given bounds 705 * 706 * @param {mat4} out mat4 frustum matrix will be written into 707 * @param {Number} left Left bound of the frustum 708 * @param {Number} right Right bound of the frustum 709 * @param {Number} bottom Bottom bound of the frustum 710 * @param {Number} top Top bound of the frustum 711 * @param {Number} near Near bound of the frustum 712 * @param {Number} far Far bound of the frustum 713 * @returns {mat4} out 714 */ 715mat4.frustum = function (out, left, right, bottom, top, near, far) { 716 var rl = 1 / (right - left), 717 tb = 1 / (top - bottom), 718 nf = 1 / (near - far); 719 out[0] = (near * 2) * rl; 720 out[1] = 0; 721 out[2] = 0; 722 out[3] = 0; 723 out[4] = 0; 724 out[5] = (near * 2) * tb; 725 out[6] = 0; 726 out[7] = 0; 727 out[8] = (right + left) * rl; 728 out[9] = (top + bottom) * tb; 729 out[10] = (far + near) * nf; 730 out[11] = -1; 731 out[12] = 0; 732 out[13] = 0; 733 out[14] = (far * near * 2) * nf; 734 out[15] = 0; 735 return out; 736}; 737 738/** 739 * Generates a perspective projection matrix with the given bounds 740 * 741 * @param {mat4} out mat4 frustum matrix will be written into 742 * @param {number} fovy Vertical field of view in radians 743 * @param {number} aspect Aspect ratio. typically viewport width/height 744 * @param {number} near Near bound of the frustum 745 * @param {number} far Far bound of the frustum 746 * @returns {mat4} out 747 */ 748mat4.perspective = function (out, fovy, aspect, near, far) { 749 var f = 1.0 / Math.tan(fovy / 2), 750 nf = 1 / (near - far); 751 out[0] = f / aspect; 752 out[1] = 0; 753 out[2] = 0; 754 out[3] = 0; 755 out[4] = 0; 756 out[5] = f; 757 out[6] = 0; 758 out[7] = 0; 759 out[8] = 0; 760 out[9] = 0; 761 out[10] = (far + near) * nf; 762 out[11] = -1; 763 out[12] = 0; 764 out[13] = 0; 765 out[14] = (2 * far * near) * nf; 766 out[15] = 0; 767 return out; 768}; 769 770/** 771 * Generates a orthogonal projection matrix with the given bounds 772 * 773 * @param {mat4} out mat4 frustum matrix will be written into 774 * @param {number} left Left bound of the frustum 775 * @param {number} right Right bound of the frustum 776 * @param {number} bottom Bottom bound of the frustum 777 * @param {number} top Top bound of the frustum 778 * @param {number} near Near bound of the frustum 779 * @param {number} far Far bound of the frustum 780 * @returns {mat4} out 781 */ 782mat4.ortho = function (out, left, right, bottom, top, near, far) { 783 var lr = 1 / (left - right), 784 bt = 1 / (bottom - top), 785 nf = 1 / (near - far); 786 out[0] = -2 * lr; 787 out[1] = 0; 788 out[2] = 0; 789 out[3] = 0; 790 out[4] = 0; 791 out[5] = -2 * bt; 792 out[6] = 0; 793 out[7] = 0; 794 out[8] = 0; 795 out[9] = 0; 796 out[10] = 2 * nf; 797 out[11] = 0; 798 out[12] = (left + right) * lr; 799 out[13] = (top + bottom) * bt; 800 out[14] = (far + near) * nf; 801 out[15] = 1; 802 return out; 803}; 804 805/** 806 * Generates a look-at matrix with the given eye position, focal point, and up axis 807 * 808 * @param {mat4} out mat4 frustum matrix will be written into 809 * @param {vec3} eye Position of the viewer 810 * @param {vec3} center Point the viewer is looking at 811 * @param {vec3} up vec3 pointing up 812 * @returns {mat4} out 813 */ 814mat4.lookAt = function (out, eye, center, up) { 815 var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, 816 eyex = eye[0], 817 eyey = eye[1], 818 eyez = eye[2], 819 upx = up[0], 820 upy = up[1], 821 upz = up[2], 822 centerx = center[0], 823 centery = center[1], 824 centerz = center[2]; 825 826 if (Math.abs(eyex - centerx) < GLMAT_EPSILON && 827 Math.abs(eyey - centery) < GLMAT_EPSILON && 828 Math.abs(eyez - centerz) < GLMAT_EPSILON) { 829 return mat4.identity(out); 830 } 831 832 z0 = eyex - centerx; 833 z1 = eyey - centery; 834 z2 = eyez - centerz; 835 836 len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); 837 z0 *= len; 838 z1 *= len; 839 z2 *= len; 840 841 x0 = upy * z2 - upz * z1; 842 x1 = upz * z0 - upx * z2; 843 x2 = upx * z1 - upy * z0; 844 len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); 845 if (!len) { 846 x0 = 0; 847 x1 = 0; 848 x2 = 0; 849 } else { 850 len = 1 / len; 851 x0 *= len; 852 x1 *= len; 853 x2 *= len; 854 } 855 856 y0 = z1 * x2 - z2 * x1; 857 y1 = z2 * x0 - z0 * x2; 858 y2 = z0 * x1 - z1 * x0; 859 860 len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); 861 if (!len) { 862 y0 = 0; 863 y1 = 0; 864 y2 = 0; 865 } else { 866 len = 1 / len; 867 y0 *= len; 868 y1 *= len; 869 y2 *= len; 870 } 871 872 out[0] = x0; 873 out[1] = y0; 874 out[2] = z0; 875 out[3] = 0; 876 out[4] = x1; 877 out[5] = y1; 878 out[6] = z1; 879 out[7] = 0; 880 out[8] = x2; 881 out[9] = y2; 882 out[10] = z2; 883 out[11] = 0; 884 out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); 885 out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); 886 out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); 887 out[15] = 1; 888 889 return out; 890}; 891 892/** 893 * Returns a string representation of a mat4 894 * 895 * @param {mat4} mat matrix to represent as a string 896 * @returns {String} string representation of the matrix 897 */ 898mat4.str = function (a) { 899 return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + 900 a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + 901 a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' + 902 a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')'; 903}; 904 905if(typeof(exports) !== 'undefined') { 906 exports.mat4 = mat4; 907} 908