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 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 glMatrix.ARRAY_TYPE(16); 36 out[0] = 1; 37 out[1] = 0; 38 out[2] = 0; 39 out[3] = 0; 40 out[4] = 0; 41 out[5] = 1; 42 out[6] = 0; 43 out[7] = 0; 44 out[8] = 0; 45 out[9] = 0; 46 out[10] = 1; 47 out[11] = 0; 48 out[12] = 0; 49 out[13] = 0; 50 out[14] = 0; 51 out[15] = 1; 52 return out; 53}; 54 55/** 56 * Creates a new mat4 initialized with values from an existing matrix 57 * 58 * @param {mat4} a matrix to clone 59 * @returns {mat4} a new 4x4 matrix 60 */ 61mat4.clone = function(a) { 62 var out = new glMatrix.ARRAY_TYPE(16); 63 out[0] = a[0]; 64 out[1] = a[1]; 65 out[2] = a[2]; 66 out[3] = a[3]; 67 out[4] = a[4]; 68 out[5] = a[5]; 69 out[6] = a[6]; 70 out[7] = a[7]; 71 out[8] = a[8]; 72 out[9] = a[9]; 73 out[10] = a[10]; 74 out[11] = a[11]; 75 out[12] = a[12]; 76 out[13] = a[13]; 77 out[14] = a[14]; 78 out[15] = a[15]; 79 return out; 80}; 81 82/** 83 * Copy the values from one mat4 to another 84 * 85 * @param {mat4} out the receiving matrix 86 * @param {mat4} a the source matrix 87 * @returns {mat4} out 88 */ 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 around the given axis 414 * 415 * @param {mat4} out the receiving matrix 416 * @param {mat4} a the matrix to rotate 417 * @param {Number} rad the angle to rotate the matrix by 418 * @param {vec3} axis the axis to rotate around 419 * @returns {mat4} out 420 */ 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) < glMatrix.EPSILON) { return null; } 433 434 len = 1 / len; 435 x *= len; 436 y *= len; 437 z *= len; 438 439 s = Math.sin(rad); 440 c = Math.cos(rad); 441 t = 1 - c; 442 443 a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; 444 a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; 445 a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; 446 447 // Construct the elements of the rotation matrix 448 b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; 449 b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; 450 b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; 451 452 // Perform rotation-specific matrix multiplication 453 out[0] = a00 * b00 + a10 * b01 + a20 * b02; 454 out[1] = a01 * b00 + a11 * b01 + a21 * b02; 455 out[2] = a02 * b00 + a12 * b01 + a22 * b02; 456 out[3] = a03 * b00 + a13 * b01 + a23 * b02; 457 out[4] = a00 * b10 + a10 * b11 + a20 * b12; 458 out[5] = a01 * b10 + a11 * b11 + a21 * b12; 459 out[6] = a02 * b10 + a12 * b11 + a22 * b12; 460 out[7] = a03 * b10 + a13 * b11 + a23 * b12; 461 out[8] = a00 * b20 + a10 * b21 + a20 * b22; 462 out[9] = a01 * b20 + a11 * b21 + a21 * b22; 463 out[10] = a02 * b20 + a12 * b21 + a22 * b22; 464 out[11] = a03 * b20 + a13 * b21 + a23 * b22; 465 466 if (a !== out) { // If the source and destination differ, copy the unchanged last row 467 out[12] = a[12]; 468 out[13] = a[13]; 469 out[14] = a[14]; 470 out[15] = a[15]; 471 } 472 return out; 473}; 474 475/** 476 * Rotates a matrix by the given angle around the X axis 477 * 478 * @param {mat4} out the receiving matrix 479 * @param {mat4} a the matrix to rotate 480 * @param {Number} rad the angle to rotate the matrix by 481 * @returns {mat4} out 482 */ 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 vector translation 606 * This is equivalent to (but much faster than): 607 * 608 * mat4.identity(dest); 609 * mat4.translate(dest, dest, vec); 610 * 611 * @param {mat4} out mat4 receiving operation result 612 * @param {vec3} v Translation vector 613 * @returns {mat4} out 614 */ 615mat4.fromTranslation = function(out, v) { 616 out[0] = 1; 617 out[1] = 0; 618 out[2] = 0; 619 out[3] = 0; 620 out[4] = 0; 621 out[5] = 1; 622 out[6] = 0; 623 out[7] = 0; 624 out[8] = 0; 625 out[9] = 0; 626 out[10] = 1; 627 out[11] = 0; 628 out[12] = v[0]; 629 out[13] = v[1]; 630 out[14] = v[2]; 631 out[15] = 1; 632 return out; 633} 634 635/** 636 * Creates a matrix from a vector scaling 637 * This is equivalent to (but much faster than): 638 * 639 * mat4.identity(dest); 640 * mat4.scale(dest, dest, vec); 641 * 642 * @param {mat4} out mat4 receiving operation result 643 * @param {vec3} v Scaling vector 644 * @returns {mat4} out 645 */ 646mat4.fromScaling = function(out, v) { 647 out[0] = v[0]; 648 out[1] = 0; 649 out[2] = 0; 650 out[3] = 0; 651 out[4] = 0; 652 out[5] = v[1]; 653 out[6] = 0; 654 out[7] = 0; 655 out[8] = 0; 656 out[9] = 0; 657 out[10] = v[2]; 658 out[11] = 0; 659 out[12] = 0; 660 out[13] = 0; 661 out[14] = 0; 662 out[15] = 1; 663 return out; 664} 665 666/** 667 * Creates a matrix from a given angle around a given axis 668 * This is equivalent to (but much faster than): 669 * 670 * mat4.identity(dest); 671 * mat4.rotate(dest, dest, rad, axis); 672 * 673 * @param {mat4} out mat4 receiving operation result 674 * @param {Number} rad the angle to rotate the matrix by 675 * @param {vec3} axis the axis to rotate around 676 * @returns {mat4} out 677 */ 678mat4.fromRotation = function(out, rad, axis) { 679 var x = axis[0], y = axis[1], z = axis[2], 680 len = Math.sqrt(x * x + y * y + z * z), 681 s, c, t; 682 683 if (Math.abs(len) < glMatrix.EPSILON) { return null; } 684 685 len = 1 / len; 686 x *= len; 687 y *= len; 688 z *= len; 689 690 s = Math.sin(rad); 691 c = Math.cos(rad); 692 t = 1 - c; 693 694 // Perform rotation-specific matrix multiplication 695 out[0] = x * x * t + c; 696 out[1] = y * x * t + z * s; 697 out[2] = z * x * t - y * s; 698 out[3] = 0; 699 out[4] = x * y * t - z * s; 700 out[5] = y * y * t + c; 701 out[6] = z * y * t + x * s; 702 out[7] = 0; 703 out[8] = x * z * t + y * s; 704 out[9] = y * z * t - x * s; 705 out[10] = z * z * t + c; 706 out[11] = 0; 707 out[12] = 0; 708 out[13] = 0; 709 out[14] = 0; 710 out[15] = 1; 711 return out; 712} 713 714/** 715 * Creates a matrix from the given angle around the X axis 716 * This is equivalent to (but much faster than): 717 * 718 * mat4.identity(dest); 719 * mat4.rotateX(dest, dest, rad); 720 * 721 * @param {mat4} out mat4 receiving operation result 722 * @param {Number} rad the angle to rotate the matrix by 723 * @returns {mat4} out 724 */ 725mat4.fromXRotation = function(out, rad) { 726 var s = Math.sin(rad), 727 c = Math.cos(rad); 728 729 // Perform axis-specific matrix multiplication 730 out[0] = 1; 731 out[1] = 0; 732 out[2] = 0; 733 out[3] = 0; 734 out[4] = 0; 735 out[5] = c; 736 out[6] = s; 737 out[7] = 0; 738 out[8] = 0; 739 out[9] = -s; 740 out[10] = c; 741 out[11] = 0; 742 out[12] = 0; 743 out[13] = 0; 744 out[14] = 0; 745 out[15] = 1; 746 return out; 747} 748 749/** 750 * Creates a matrix from the given angle around the Y axis 751 * This is equivalent to (but much faster than): 752 * 753 * mat4.identity(dest); 754 * mat4.rotateY(dest, dest, rad); 755 * 756 * @param {mat4} out mat4 receiving operation result 757 * @param {Number} rad the angle to rotate the matrix by 758 * @returns {mat4} out 759 */ 760mat4.fromYRotation = function(out, rad) { 761 var s = Math.sin(rad), 762 c = Math.cos(rad); 763 764 // Perform axis-specific matrix multiplication 765 out[0] = c; 766 out[1] = 0; 767 out[2] = -s; 768 out[3] = 0; 769 out[4] = 0; 770 out[5] = 1; 771 out[6] = 0; 772 out[7] = 0; 773 out[8] = s; 774 out[9] = 0; 775 out[10] = c; 776 out[11] = 0; 777 out[12] = 0; 778 out[13] = 0; 779 out[14] = 0; 780 out[15] = 1; 781 return out; 782} 783 784/** 785 * Creates a matrix from the given angle around the Z axis 786 * This is equivalent to (but much faster than): 787 * 788 * mat4.identity(dest); 789 * mat4.rotateZ(dest, dest, rad); 790 * 791 * @param {mat4} out mat4 receiving operation result 792 * @param {Number} rad the angle to rotate the matrix by 793 * @returns {mat4} out 794 */ 795mat4.fromZRotation = function(out, rad) { 796 var s = Math.sin(rad), 797 c = Math.cos(rad); 798 799 // Perform axis-specific matrix multiplication 800 out[0] = c; 801 out[1] = s; 802 out[2] = 0; 803 out[3] = 0; 804 out[4] = -s; 805 out[5] = c; 806 out[6] = 0; 807 out[7] = 0; 808 out[8] = 0; 809 out[9] = 0; 810 out[10] = 1; 811 out[11] = 0; 812 out[12] = 0; 813 out[13] = 0; 814 out[14] = 0; 815 out[15] = 1; 816 return out; 817} 818 819/** 820 * Creates a matrix from a quaternion rotation and vector translation 821 * This is equivalent to (but much faster than): 822 * 823 * mat4.identity(dest); 824 * mat4.translate(dest, vec); 825 * var quatMat = mat4.create(); 826 * quat4.toMat4(quat, quatMat); 827 * mat4.multiply(dest, quatMat); 828 * 829 * @param {mat4} out mat4 receiving operation result 830 * @param {quat4} q Rotation quaternion 831 * @param {vec3} v Translation vector 832 * @returns {mat4} out 833 */ 834mat4.fromRotationTranslation = function (out, q, v) { 835 // Quaternion math 836 var x = q[0], y = q[1], z = q[2], w = q[3], 837 x2 = x + x, 838 y2 = y + y, 839 z2 = z + z, 840 841 xx = x * x2, 842 xy = x * y2, 843 xz = x * z2, 844 yy = y * y2, 845 yz = y * z2, 846 zz = z * z2, 847 wx = w * x2, 848 wy = w * y2, 849 wz = w * z2; 850 851 out[0] = 1 - (yy + zz); 852 out[1] = xy + wz; 853 out[2] = xz - wy; 854 out[3] = 0; 855 out[4] = xy - wz; 856 out[5] = 1 - (xx + zz); 857 out[6] = yz + wx; 858 out[7] = 0; 859 out[8] = xz + wy; 860 out[9] = yz - wx; 861 out[10] = 1 - (xx + yy); 862 out[11] = 0; 863 out[12] = v[0]; 864 out[13] = v[1]; 865 out[14] = v[2]; 866 out[15] = 1; 867 868 return out; 869}; 870 871/** 872 * Creates a matrix from a quaternion rotation, vector translation and vector scale 873 * This is equivalent to (but much faster than): 874 * 875 * mat4.identity(dest); 876 * mat4.translate(dest, vec); 877 * var quatMat = mat4.create(); 878 * quat4.toMat4(quat, quatMat); 879 * mat4.multiply(dest, quatMat); 880 * mat4.scale(dest, scale) 881 * 882 * @param {mat4} out mat4 receiving operation result 883 * @param {quat4} q Rotation quaternion 884 * @param {vec3} v Translation vector 885 * @param {vec3} s Scaling vector 886 * @returns {mat4} out 887 */ 888mat4.fromRotationTranslationScale = function (out, q, v, s) { 889 // Quaternion math 890 var x = q[0], y = q[1], z = q[2], w = q[3], 891 x2 = x + x, 892 y2 = y + y, 893 z2 = z + z, 894 895 xx = x * x2, 896 xy = x * y2, 897 xz = x * z2, 898 yy = y * y2, 899 yz = y * z2, 900 zz = z * z2, 901 wx = w * x2, 902 wy = w * y2, 903 wz = w * z2, 904 sx = s[0], 905 sy = s[1], 906 sz = s[2]; 907 908 out[0] = (1 - (yy + zz)) * sx; 909 out[1] = (xy + wz) * sx; 910 out[2] = (xz - wy) * sx; 911 out[3] = 0; 912 out[4] = (xy - wz) * sy; 913 out[5] = (1 - (xx + zz)) * sy; 914 out[6] = (yz + wx) * sy; 915 out[7] = 0; 916 out[8] = (xz + wy) * sz; 917 out[9] = (yz - wx) * sz; 918 out[10] = (1 - (xx + yy)) * sz; 919 out[11] = 0; 920 out[12] = v[0]; 921 out[13] = v[1]; 922 out[14] = v[2]; 923 out[15] = 1; 924 925 return out; 926}; 927 928/** 929 * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin 930 * This is equivalent to (but much faster than): 931 * 932 * mat4.identity(dest); 933 * mat4.translate(dest, vec); 934 * mat4.translate(dest, origin); 935 * var quatMat = mat4.create(); 936 * quat4.toMat4(quat, quatMat); 937 * mat4.multiply(dest, quatMat); 938 * mat4.scale(dest, scale) 939 * mat4.translate(dest, negativeOrigin); 940 * 941 * @param {mat4} out mat4 receiving operation result 942 * @param {quat4} q Rotation quaternion 943 * @param {vec3} v Translation vector 944 * @param {vec3} s Scaling vector 945 * @param {vec3} o The origin vector around which to scale and rotate 946 * @returns {mat4} out 947 */ 948mat4.fromRotationTranslationScaleOrigin = function (out, q, v, s, o) { 949 // Quaternion math 950 var x = q[0], y = q[1], z = q[2], w = q[3], 951 x2 = x + x, 952 y2 = y + y, 953 z2 = z + z, 954 955 xx = x * x2, 956 xy = x * y2, 957 xz = x * z2, 958 yy = y * y2, 959 yz = y * z2, 960 zz = z * z2, 961 wx = w * x2, 962 wy = w * y2, 963 wz = w * z2, 964 965 sx = s[0], 966 sy = s[1], 967 sz = s[2], 968 969 ox = o[0], 970 oy = o[1], 971 oz = o[2]; 972 973 out[0] = (1 - (yy + zz)) * sx; 974 out[1] = (xy + wz) * sx; 975 out[2] = (xz - wy) * sx; 976 out[3] = 0; 977 out[4] = (xy - wz) * sy; 978 out[5] = (1 - (xx + zz)) * sy; 979 out[6] = (yz + wx) * sy; 980 out[7] = 0; 981 out[8] = (xz + wy) * sz; 982 out[9] = (yz - wx) * sz; 983 out[10] = (1 - (xx + yy)) * sz; 984 out[11] = 0; 985 out[12] = v[0] + ox - (out[0] * ox + out[4] * oy + out[8] * oz); 986 out[13] = v[1] + oy - (out[1] * ox + out[5] * oy + out[9] * oz); 987 out[14] = v[2] + oz - (out[2] * ox + out[6] * oy + out[10] * oz); 988 out[15] = 1; 989 990 return out; 991}; 992 993mat4.fromQuat = function (out, q) { 994 var x = q[0], y = q[1], z = q[2], w = q[3], 995 x2 = x + x, 996 y2 = y + y, 997 z2 = z + z, 998 999 xx = x * x2, 1000 yx = y * x2, 1001 yy = y * y2, 1002 zx = z * x2, 1003 zy = z * y2, 1004 zz = z * z2, 1005 wx = w * x2, 1006 wy = w * y2, 1007 wz = w * z2; 1008 1009 out[0] = 1 - yy - zz; 1010 out[1] = yx + wz; 1011 out[2] = zx - wy; 1012 out[3] = 0; 1013 1014 out[4] = yx - wz; 1015 out[5] = 1 - xx - zz; 1016 out[6] = zy + wx; 1017 out[7] = 0; 1018 1019 out[8] = zx + wy; 1020 out[9] = zy - wx; 1021 out[10] = 1 - xx - yy; 1022 out[11] = 0; 1023 1024 out[12] = 0; 1025 out[13] = 0; 1026 out[14] = 0; 1027 out[15] = 1; 1028 1029 return out; 1030}; 1031 1032/** 1033 * Generates a frustum matrix with the given bounds 1034 * 1035 * @param {mat4} out mat4 frustum matrix will be written into 1036 * @param {Number} left Left bound of the frustum 1037 * @param {Number} right Right bound of the frustum 1038 * @param {Number} bottom Bottom bound of the frustum 1039 * @param {Number} top Top bound of the frustum 1040 * @param {Number} near Near bound of the frustum 1041 * @param {Number} far Far bound of the frustum 1042 * @returns {mat4} out 1043 */ 1044mat4.frustum = function (out, left, right, bottom, top, near, far) { 1045 var rl = 1 / (right - left), 1046 tb = 1 / (top - bottom), 1047 nf = 1 / (near - far); 1048 out[0] = (near * 2) * rl; 1049 out[1] = 0; 1050 out[2] = 0; 1051 out[3] = 0; 1052 out[4] = 0; 1053 out[5] = (near * 2) * tb; 1054 out[6] = 0; 1055 out[7] = 0; 1056 out[8] = (right + left) * rl; 1057 out[9] = (top + bottom) * tb; 1058 out[10] = (far + near) * nf; 1059 out[11] = -1; 1060 out[12] = 0; 1061 out[13] = 0; 1062 out[14] = (far * near * 2) * nf; 1063 out[15] = 0; 1064 return out; 1065}; 1066 1067/** 1068 * Generates a perspective projection matrix with the given bounds 1069 * 1070 * @param {mat4} out mat4 frustum matrix will be written into 1071 * @param {number} fovy Vertical field of view in radians 1072 * @param {number} aspect Aspect ratio. typically viewport width/height 1073 * @param {number} near Near bound of the frustum 1074 * @param {number} far Far bound of the frustum 1075 * @returns {mat4} out 1076 */ 1077mat4.perspective = function (out, fovy, aspect, near, far) { 1078 var f = 1.0 / Math.tan(fovy / 2), 1079 nf = 1 / (near - far); 1080 out[0] = f / aspect; 1081 out[1] = 0; 1082 out[2] = 0; 1083 out[3] = 0; 1084 out[4] = 0; 1085 out[5] = f; 1086 out[6] = 0; 1087 out[7] = 0; 1088 out[8] = 0; 1089 out[9] = 0; 1090 out[10] = (far + near) * nf; 1091 out[11] = -1; 1092 out[12] = 0; 1093 out[13] = 0; 1094 out[14] = (2 * far * near) * nf; 1095 out[15] = 0; 1096 return out; 1097}; 1098 1099/** 1100 * Generates a perspective projection matrix with the given field of view. 1101 * This is primarily useful for generating projection matrices to be used 1102 * with the still experiemental WebVR API. 1103 * 1104 * @param {mat4} out mat4 frustum matrix will be written into 1105 * @param {number} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees 1106 * @param {number} near Near bound of the frustum 1107 * @param {number} far Far bound of the frustum 1108 * @returns {mat4} out 1109 */ 1110mat4.perspectiveFromFieldOfView = function (out, fov, near, far) { 1111 var upTan = Math.tan(fov.upDegrees * Math.PI/180.0), 1112 downTan = Math.tan(fov.downDegrees * Math.PI/180.0), 1113 leftTan = Math.tan(fov.leftDegrees * Math.PI/180.0), 1114 rightTan = Math.tan(fov.rightDegrees * Math.PI/180.0), 1115 xScale = 2.0 / (leftTan + rightTan), 1116 yScale = 2.0 / (upTan + downTan); 1117 1118 out[0] = xScale; 1119 out[1] = 0.0; 1120 out[2] = 0.0; 1121 out[3] = 0.0; 1122 out[4] = 0.0; 1123 out[5] = yScale; 1124 out[6] = 0.0; 1125 out[7] = 0.0; 1126 out[8] = -((leftTan - rightTan) * xScale * 0.5); 1127 out[9] = ((upTan - downTan) * yScale * 0.5); 1128 out[10] = far / (near - far); 1129 out[11] = -1.0; 1130 out[12] = 0.0; 1131 out[13] = 0.0; 1132 out[14] = (far * near) / (near - far); 1133 out[15] = 0.0; 1134 return out; 1135} 1136 1137/** 1138 * Generates a orthogonal projection matrix with the given bounds 1139 * 1140 * @param {mat4} out mat4 frustum matrix will be written into 1141 * @param {number} left Left bound of the frustum 1142 * @param {number} right Right bound of the frustum 1143 * @param {number} bottom Bottom bound of the frustum 1144 * @param {number} top Top bound of the frustum 1145 * @param {number} near Near bound of the frustum 1146 * @param {number} far Far bound of the frustum 1147 * @returns {mat4} out 1148 */ 1149mat4.ortho = function (out, left, right, bottom, top, near, far) { 1150 var lr = 1 / (left - right), 1151 bt = 1 / (bottom - top), 1152 nf = 1 / (near - far); 1153 out[0] = -2 * lr; 1154 out[1] = 0; 1155 out[2] = 0; 1156 out[3] = 0; 1157 out[4] = 0; 1158 out[5] = -2 * bt; 1159 out[6] = 0; 1160 out[7] = 0; 1161 out[8] = 0; 1162 out[9] = 0; 1163 out[10] = 2 * nf; 1164 out[11] = 0; 1165 out[12] = (left + right) * lr; 1166 out[13] = (top + bottom) * bt; 1167 out[14] = (far + near) * nf; 1168 out[15] = 1; 1169 return out; 1170}; 1171 1172/** 1173 * Generates a look-at matrix with the given eye position, focal point, and up axis 1174 * 1175 * @param {mat4} out mat4 frustum matrix will be written into 1176 * @param {vec3} eye Position of the viewer 1177 * @param {vec3} center Point the viewer is looking at 1178 * @param {vec3} up vec3 pointing up 1179 * @returns {mat4} out 1180 */ 1181mat4.lookAt = function (out, eye, center, up) { 1182 var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, 1183 eyex = eye[0], 1184 eyey = eye[1], 1185 eyez = eye[2], 1186 upx = up[0], 1187 upy = up[1], 1188 upz = up[2], 1189 centerx = center[0], 1190 centery = center[1], 1191 centerz = center[2]; 1192 1193 if (Math.abs(eyex - centerx) < glMatrix.EPSILON && 1194 Math.abs(eyey - centery) < glMatrix.EPSILON && 1195 Math.abs(eyez - centerz) < glMatrix.EPSILON) { 1196 return mat4.identity(out); 1197 } 1198 1199 z0 = eyex - centerx; 1200 z1 = eyey - centery; 1201 z2 = eyez - centerz; 1202 1203 len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); 1204 z0 *= len; 1205 z1 *= len; 1206 z2 *= len; 1207 1208 x0 = upy * z2 - upz * z1; 1209 x1 = upz * z0 - upx * z2; 1210 x2 = upx * z1 - upy * z0; 1211 len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); 1212 if (!len) { 1213 x0 = 0; 1214 x1 = 0; 1215 x2 = 0; 1216 } else { 1217 len = 1 / len; 1218 x0 *= len; 1219 x1 *= len; 1220 x2 *= len; 1221 } 1222 1223 y0 = z1 * x2 - z2 * x1; 1224 y1 = z2 * x0 - z0 * x2; 1225 y2 = z0 * x1 - z1 * x0; 1226 1227 len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); 1228 if (!len) { 1229 y0 = 0; 1230 y1 = 0; 1231 y2 = 0; 1232 } else { 1233 len = 1 / len; 1234 y0 *= len; 1235 y1 *= len; 1236 y2 *= len; 1237 } 1238 1239 out[0] = x0; 1240 out[1] = y0; 1241 out[2] = z0; 1242 out[3] = 0; 1243 out[4] = x1; 1244 out[5] = y1; 1245 out[6] = z1; 1246 out[7] = 0; 1247 out[8] = x2; 1248 out[9] = y2; 1249 out[10] = z2; 1250 out[11] = 0; 1251 out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); 1252 out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); 1253 out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); 1254 out[15] = 1; 1255 1256 return out; 1257}; 1258 1259/** 1260 * Returns a string representation of a mat4 1261 * 1262 * @param {mat4} mat matrix to represent as a string 1263 * @returns {String} string representation of the matrix 1264 */ 1265mat4.str = function (a) { 1266 return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + 1267 a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + 1268 a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' + 1269 a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')'; 1270}; 1271 1272/** 1273 * Returns Frobenius norm of a mat4 1274 * 1275 * @param {mat4} a the matrix to calculate Frobenius norm of 1276 * @returns {Number} Frobenius norm 1277 */ 1278mat4.frob = function (a) { 1279 return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) )) 1280}; 1281 1282 1283module.exports = mat4; 1284