1 /* 2 Copyright (c) 2008 Seneca College 3 Licenced under the MIT License (http://www.c3dl.org/index.php/mit-license/) 4 */ 5 // Written By: Mark Paruzel 6 // Date: April 11, 2008 7 // Project: Canvas 3D Library 8 9 // ----------------------------------------------------------------------------- 10 // NOTE: This group of functions act upon an array of sixteen values which 11 // represent a matrix orientation. How a Matrix Works: 12 // 13 // - An Orientation uses the 3 Axis in a 3D world: Up, Forward and Left 14 // (Right handed system). 15 // - A 4x4 Matrix adds in a Translation into the matrix along with an 16 // Orientation. 17 // 18 // Matrix uses column-major order which means elements are listed column 19 // first 20 // 21 // +- -+ 22 // | Right.x, Up.x, Fwd.x, Pos.x | 23 // | Right.y, Up.y, Fwd.y, Pos.y | 24 // | Right.z, Up.z, Fwd.z, Pos.z | 25 // | 0.0, 0.0, 0.0, 1.0 | 26 // +- -+ 27 // 28 // Array Indices: 29 // +- -+ 30 // | 0, 4, 8, 11 | 31 // | 1, 5, 6, 12 | 32 // | 2, 6, 9, 13 | 33 // | 3, 7, 10, 15 | 34 // +- -+ 35 // ----------------------------------------------------------------------------- 36 37 /** 38 Is the Matrix 'mat' is valid? That is, does it contain 16 39 values and are all the values numbers? 40 41 @param {Array} mat The matrix to check. 42 43 @returns {boolean} True if the object 'mat' is a matrix, 44 false otherwise. 45 */ 46 c3dl.isValidMatrix = function(mat) 47 { 48 // Check if the value being passed is an array 49 if (mat instanceof Array) 50 { 51 // Must be array of 16 Values 52 if (mat.length == 16) 53 { 54 for (var i = 0; i < 16; i++) 55 { 56 // Check for bad values 57 if (isNaN(mat[i])) return false; 58 } 59 60 return true; 61 } 62 } 63 64 return false; 65 } 66 67 68 /** 69 Create an identity matrix. An identity matrix is a matrix in 70 which all the elements are zero, save on the main diagonal 71 where all elements are ones.<br /> 72 <br /> 73 Example: 74 <pre> 75 +- -+ 76 | 1, 0, 0, 0 | 77 | 0, 1, 0, 0 | 78 | 0, 0, 1, 0 | 79 | 0, 0, 0, 1 | 80 +- -+ 81 </pre> 82 83 An identity matrix is equivalent to the number one in some respects, 84 that is multiplying matrix M by an identity matrix will yield M. 85 Matrix multiplication with an identity matrix is one case in which 86 matrix multiplication is commutative. 87 M * I = M 88 I * M = M 89 <br /> 90 91 @returns {Array} An identity matrix. 92 */ 93 c3dl.makeIdentityMatrix = function() 94 { 95 return [1.0, 0.0, 0.0, 0.0, 96 0.0, 1.0, 0.0, 0.0, 97 0.0, 0.0, 1.0, 0.0, 98 0.0, 0.0, 0.0, 1.0]; 99 } 100 101 102 /** 103 Create a Zero matrix, that is a matrix in which each component 104 of the matrix is zero. 105 106 @returns {Array} A zero matrix. 107 */ 108 c3dl.makeZeroMatrix = function() 109 { 110 return [0.0, 0.0, 0.0, 0.0, 111 0.0, 0.0, 0.0, 0.0, 112 0.0, 0.0, 0.0, 0.0, 113 0.0, 0.0, 0.0, 0.0]; 114 } 115 116 /** 117 Set the elements of a matrix. Supply the values in column-major 118 ordering. 119 120 e[r][c], e01 = row 0, column 1 121 122 @param {Array} mat The matrix to set 123 @param {float} e00 Column 0, Row 0 124 @param {float} e01 125 @param {float} e02 126 @param {float} e03 127 @param {float} e10 Column 1, Row 0 128 @param {float} e11 129 @param {float} e12 130 @param {float} e13 131 @param {float} e20 Column 2, Row 0 132 @param {float} e21 133 @param {float} e22 134 @param {float} e23 135 @param {float} e30 Column 3, Row 0 136 @param {float} e31 137 @param {float} e32 138 @param {float} e33 139 */ 140 c3dl.setMatrix = function(mat, e00, e01, e02, e03, 141 e10, e11, e12, e13, 142 e20, e21, e22, e23, 143 e30, e31, e32, e33) 144 { 145 mat[0] = e00; 146 mat[1] = e01; 147 mat[2] = e02; 148 mat[3] = e03; 149 150 mat[4] = e10; 151 mat[5] = e11; 152 mat[6] = e12; 153 mat[7] = e13; 154 155 mat[8] = e20; 156 mat[9] = e21; 157 mat[10] = e22; 158 mat[11] = e23; 159 160 mat[12] = e30; 161 mat[13] = e31; 162 mat[14] = e32; 163 mat[15] = e33; 164 } 165 166 /** 167 Make a matrix by providing each component. Supply the values in colum-major order.<br /> 168 Indices: 169 <pre> 170 +- -+ 171 | 0, 4, 8, 12 | 172 | 1, 5, 9, 13 | 173 | 2, 6, 10, 14 | 174 | 3, 7, 11, 15 | 175 +- -+ 176 </pre> 177 178 @param {float} e00 Element at row 0 column 0. 179 @param {float} e01 Element at row 1 column 0. 180 @param {float} e02 Element at row 2 column 0. 181 @param {float} e03 Element at row 3 column 0. 182 @param {float} e10 Element at row 0 column 1. 183 @param {float} e11 Element at row 1 column 1. 184 @param {float} e12 Element at row 2 column 1. 185 @param {float} e13 Element at row 3 column 1. 186 @param {float} e20 Element at row 0 column 2. 187 @param {float} e21 Element at row 1 column 2. 188 @param {float} e22 Element at row 2 column 2. 189 @param {float} e23 Element at row 3 column 2. 190 @param {float} e30 Element at row 0 column 3. 191 @param {float} e31 Element at row 1 column 3. 192 @param {float} e32 Element at row 2 column 3. 193 @param {float} e33 Element at row 3 column 3. 194 195 @return {Array} A matrix defined by the provided arguments. 196 */ 197 c3dl.makeMatrix = function( e00, e01, e02, e03, 198 e10, e11, e12, e13, 199 e20, e21, e22, e23, 200 e30, e31, e32, e33) 201 { 202 return [!isNaN(e00) ? parseFloat(e00) : 0.0, 203 !isNaN(e01) ? parseFloat(e01) : 0.0, 204 !isNaN(e02) ? parseFloat(e02) : 0.0, 205 !isNaN(e03) ? parseFloat(e03) : 0.0, 206 !isNaN(e10) ? parseFloat(e10) : 0.0, 207 !isNaN(e11) ? parseFloat(e11) : 0.0, 208 !isNaN(e12) ? parseFloat(e12) : 0.0, 209 !isNaN(e13) ? parseFloat(e13) : 0.0, 210 !isNaN(e20) ? parseFloat(e20) : 0.0, 211 !isNaN(e21) ? parseFloat(e21) : 0.0, 212 !isNaN(e22) ? parseFloat(e22) : 0.0, 213 !isNaN(e23) ? parseFloat(e23) : 0.0, 214 !isNaN(e30) ? parseFloat(e30) : 0.0, 215 !isNaN(e31) ? parseFloat(e31) : 0.0, 216 !isNaN(e32) ? parseFloat(e32) : 0.0, 217 !isNaN(e33) ? parseFloat(e33) : 0.0]; 218 } 219 220 /** 221 Check if two matrices are equal. Assumes for performance reasons 222 that the matrices passed in are valid. Two matrices are equal if 223 they're corresponding components are equal or their difference is 224 less than TOLERANCE. This tolerance is simply a small number used 225 as a buffer due to floating point inaccuracies. 226 227 @param {Array} matrix1 The first matrix. 228 @param {Array} matrix2 The second matrix. 229 230 @return {boolean} True if matrices are equal, false otherwise. 231 */ 232 c3dl.matricesEqual = function(matrix1, matrix2) 233 { 234 var areEqual = true; 235 236 // stop as soon as we find an element that is not equal 237 for(var i = 0; areEqual && i < 16; i++) 238 { 239 // if it goes beyond the threshold or tolerance, we can stop 240 if( Math.abs( matrix1[i] - matrix2[i]) > c3dl.TOLERANCE) 241 { 242 areEqual = false; 243 } 244 } 245 246 return areEqual; 247 } 248 249 250 /** 251 */ 252 c3dl.makePoseMatrix = function(vecLeft, vecUp, vecFrwd, vecPos) 253 { 254 if (c3dl.isValidVector(vecLeft) && c3dl.isValidVector(vecUp) && 255 c3dl.isValidVector(vecFrwd) && c3dl.isValidVector(vecPos)) 256 { 257 // +- -+ 258 // | Left.x, Up.y, Dir.x, Pos.x | 259 // | Left.y, Up.x, Dir.y, Pos.y | 260 // | Left.z, Up.z, Dir.z, Pos.z | 261 // | 0.0, 0.0, 0.0, 1.0 | 262 // +- -+ 263 264 var mat = new Array(16); 265 266 // Left 267 mat[0] = vecLeft[0]; 268 mat[1] = vecLeft[1]; 269 mat[2] = vecLeft[2]; 270 mat[3] = 0.0; 271 272 // Up 273 mat[4] = vecUp[0]; 274 mat[5] = vecUp[1]; 275 mat[6] = vecUp[2]; 276 mat[7] = 0.0; 277 278 // Forward 279 mat[8] = vecFrwd[0]; 280 mat[9] = vecFrwd[1]; 281 mat[10] = vecFrwd[2]; 282 mat[11] = 0.0; 283 284 // Position 285 mat[12] = vecPos[0]; 286 mat[13] = vecPos[1]; 287 mat[14] = vecPos[2]; 288 mat[15] = 1.0; 289 290 return mat; 291 } 292 293 c3dl.debug.logWarning('makePoseMatrix() called with a parameters that are not valid'); 294 return null; 295 } 296 297 298 /** 299 Get the transpose of matrix 'mat'. A transposed matrix is created 300 by interchanging the rows and columns of a matrix. 301 302 Transposing the following matrix, 303 <pre> 304 +- -+ 305 | A, B, C, D | 306 | E, F, G, H | 307 | I, J, K, L | 308 | M, N, O, P | 309 +- -+ 310 </pre> 311 312 would yield: 313 <pre> 314 +- -+ 315 | A, E, I, M | 316 | B, F, J, N | 317 | C, G, K, O | 318 | D, H, L, P | 319 +- -+ 320 </pre> 321 322 @param {Array} mat Matrix to transpose. 323 324 @returns {Array} The transposed matrix if the passed in matrix 325 was valid, otherwise returns null. 326 */ 327 c3dl.transposeMatrix = function(mat) 328 { 329 if (c3dl.isValidMatrix(mat)) 330 { 331 // Transpose this matrix 332 return [mat[0], mat[4], mat[8], mat[12], 333 mat[1], mat[5], mat[9], mat[13], 334 mat[2], mat[6], mat[10], mat[14], 335 mat[3], mat[7], mat[11], mat[15]]; 336 } 337 338 c3dl.debug.logWarning('transposeMatrix() called with a parameter that is not a proper Matrix'); 339 return null; 340 } 341 342 343 /** 344 Get the inverse of matrix 'mat'. Matrix-matrix division is not 345 defined mathematically, but there is a multiplicative inverse 346 operation which is useful in solving some matrix equations. 347 Note that only matrices with a determinant not equal to zero 348 will have an inverse. There is no need to check if first if 349 the matrix has a determinant not equal to zero as this function 350 does that anyway. 351 352 @param {Array} mat The Matrix for which the inverse is 353 required. 354 355 @returns {Array} The inverse of matrix 'mat' if it has one 356 */ 357 c3dl.inverseMatrix = function(mat) 358 { 359 if (c3dl.isValidMatrix(mat)) 360 { 361 var kInv = []; 362 var fA0 = mat[ 0] * mat[ 5] - mat[ 1] * mat[ 4]; 363 var fA1 = mat[ 0] * mat[ 6] - mat[ 2] * mat[ 4]; 364 var fA2 = mat[ 0] * mat[ 7] - mat[ 3] * mat[ 4]; 365 var fA3 = mat[ 1] * mat[ 6] - mat[ 2] * mat[ 5]; 366 var fA4 = mat[ 1] * mat[ 7] - mat[ 3] * mat[ 5]; 367 var fA5 = mat[ 2] * mat[ 7] - mat[ 3] * mat[ 6]; 368 var fB0 = mat[ 8] * mat[13] - mat[ 9] * mat[12]; 369 var fB1 = mat[ 8] * mat[14] - mat[10] * mat[12]; 370 var fB2 = mat[ 8] * mat[15] - mat[11] * mat[12]; 371 var fB3 = mat[ 9] * mat[14] - mat[10] * mat[13]; 372 var fB4 = mat[ 9] * mat[15] - mat[11] * mat[13]; 373 var fB5 = mat[10] * mat[15] - mat[11] * mat[14]; 374 375 // Determinant 376 var fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0; 377 378 // Account for a very small value 379 if (Math.abs(fDet) <= 1e-9) 380 { 381 c3dl.debug.logWarning('inverseMatrix() failed due to bad values'); 382 return null; 383 } 384 385 kInv[ 0] = + mat[ 5] * fB5 - mat[ 6] * fB4 + mat[ 7] * fB3; 386 kInv[ 4] = - mat[ 4] * fB5 + mat[ 6] * fB2 - mat[ 7] * fB1; 387 kInv[ 8] = + mat[ 4] * fB4 - mat[ 5] * fB2 + mat[ 7] * fB0; 388 kInv[12] = - mat[ 4] * fB3 + mat[ 5] * fB1 - mat[ 6] * fB0; 389 kInv[ 1] = - mat[ 1] * fB5 + mat[ 2] * fB4 - mat[ 3] * fB3; 390 kInv[ 5] = + mat[ 0] * fB5 - mat[ 2] * fB2 + mat[ 3] * fB1; 391 kInv[ 9] = - mat[ 0] * fB4 + mat[ 1] * fB2 - mat[ 3] * fB0; 392 kInv[13] = + mat[ 0] * fB3 - mat[ 1] * fB1 + mat[ 2] * fB0; 393 kInv[ 2] = + mat[13] * fA5 - mat[14] * fA4 + mat[15] * fA3; 394 kInv[ 6] = - mat[12] * fA5 + mat[14] * fA2 - mat[15] * fA1; 395 kInv[10] = + mat[12] * fA4 - mat[13] * fA2 + mat[15] * fA0; 396 kInv[14] = - mat[12] * fA3 + mat[13] * fA1 - mat[14] * fA0; 397 kInv[ 3] = - mat[ 9] * fA5 + mat[10] * fA4 - mat[11] * fA3; 398 kInv[ 7] = + mat[ 8] * fA5 - mat[10] * fA2 + mat[11] * fA1; 399 kInv[11] = - mat[ 8] * fA4 + mat[ 9] * fA2 - mat[11] * fA0; 400 kInv[15] = + mat[ 8] * fA3 - mat[ 9] * fA1 + mat[10] * fA0; 401 402 // Inverse using Determinant 403 var fInvDet = 1.0 / fDet; 404 kInv[ 0] *= fInvDet; 405 kInv[ 1] *= fInvDet; 406 kInv[ 2] *= fInvDet; 407 kInv[ 3] *= fInvDet; 408 kInv[ 4] *= fInvDet; 409 kInv[ 5] *= fInvDet; 410 kInv[ 6] *= fInvDet; 411 kInv[ 7] *= fInvDet; 412 kInv[ 8] *= fInvDet; 413 kInv[ 9] *= fInvDet; 414 kInv[10] *= fInvDet; 415 kInv[11] *= fInvDet; 416 kInv[12] *= fInvDet; 417 kInv[13] *= fInvDet; 418 kInv[14] *= fInvDet; 419 kInv[15] *= fInvDet; 420 421 // Check if our matrix is correct 422 if (c3dl.isValidMatrix(kInv)) 423 { 424 return kInv; 425 } 426 427 // Just in case the calculation fails, return a null 428 c3dl.debug.logWarning('inverseMatrix() failed due to math errors'); 429 return null; 430 } 431 432 c3dl.debug.logWarning('inverseMatrix() called with a parameter that is not a proper Matrix'); 433 return null; 434 435 } 436 437 438 /** 439 Get the matrix determinant of 'mat'. 440 441 @param {Array} mat The matrix for which the determinant 442 is required. 443 444 @returns {float} The matrix determinant of 'mat' or null if 445 'mat' is invalid. 446 */ 447 c3dl.matrixDeterminant = function(mat) 448 { 449 if (c3dl.isValidMatrix(mat)) 450 { 451 var fA0 = mat[ 0] * mat[ 5] - mat[ 1] * mat[ 4]; 452 var fA1 = mat[ 0] * mat[ 6] - mat[ 2] * mat[ 4]; 453 var fA2 = mat[ 0] * mat[ 7] - mat[ 3] * mat[ 4]; 454 var fA3 = mat[ 1] * mat[ 6] - mat[ 2] * mat[ 5]; 455 var fA4 = mat[ 1] * mat[ 7] - mat[ 3] * mat[ 5]; 456 var fA5 = mat[ 2] * mat[ 7] - mat[ 3] * mat[ 6]; 457 var fB0 = mat[ 8] * mat[13] - mat[ 9] * mat[12]; 458 var fB1 = mat[ 8] * mat[14] - mat[10] * mat[12]; 459 var fB2 = mat[ 8] * mat[15] - mat[11] * mat[12]; 460 var fB3 = mat[ 9] * mat[14] - mat[10] * mat[13]; 461 var fB4 = mat[ 9] * mat[15] - mat[11] * mat[13]; 462 var fB5 = mat[10] * mat[15] - mat[11] * mat[14]; 463 464 // Construct the Determinant 465 var fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0; 466 467 return fDet; 468 } 469 470 c3dl.debug.logWarning('matrixDeterminant() called with a parameter that is not a proper Matrix'); 471 return null; 472 } 473 474 475 476 /** 477 Get the adjoint matrix of matrix 'mat'. 478 479 @param {Array} mat The matrix which the adjoint is required. 480 481 @returns {Array} the adjoint matrix of 'mat' if it was valid, otherwise 482 returns null. 483 */ 484 c3dl.matrixAdjoint = function(mat) 485 { 486 if (c3dl.isValidMatrix(mat)) 487 { 488 var k = []; 489 var fA0 = mat[ 0] * mat[ 5] - mat[ 1] * mat[ 4]; 490 var fA1 = mat[ 0] * mat[ 6] - mat[ 2] * mat[ 4]; 491 var fA2 = mat[ 0] * mat[ 7] - mat[ 3] * mat[ 4]; 492 var fA3 = mat[ 1] * mat[ 6] - mat[ 2] * mat[ 5]; 493 var fA4 = mat[ 1] * mat[ 7] - mat[ 3] * mat[ 5]; 494 var fA5 = mat[ 2] * mat[ 7] - mat[ 3] * mat[ 6]; 495 var fB0 = mat[ 8] * mat[13] - mat[ 9] * mat[12]; 496 var fB1 = mat[ 8] * mat[14] - mat[10] * mat[12]; 497 var fB2 = mat[ 8] * mat[15] - mat[11] * mat[12]; 498 var fB3 = mat[ 9] * mat[14] - mat[10] * mat[13]; 499 var fB4 = mat[ 9] * mat[15] - mat[11] * mat[13]; 500 var fB5 = mat[10] * mat[15] - mat[11] * mat[14]; 501 502 // Adjoint 503 k = [ mat[ 5] * fB5 - mat[ 6] * fB4 + mat[ 7] * fB3, 504 - mat[ 1] * fB5 + mat[ 2] * fB4 - mat[ 3] * fB3, 505 mat[13] * fA5 - mat[14] * fA4 + mat[15] * fA3, 506 - mat[ 9] * fA5 + mat[10] * fA4 - mat[11] * fA3, 507 - mat[ 4] * fB5 + mat[ 6] * fB2 - mat[ 7] * fB1, 508 mat[ 0] * fB5 - mat[ 2] * fB2 + mat[ 3] * fB1, 509 - mat[12] * fA5 + mat[14] * fA2 - mat[15] * fA1, 510 mat[ 8] * fA5 - mat[10] * fA2 + mat[11] * fA1, 511 mat[ 4] * fB4 - mat[ 5] * fB2 + mat[ 7] * fB0, 512 - mat[ 0] * fB4 + mat[ 1] * fB2 - mat[ 3] * fB0, 513 mat[12] * fA4 - mat[13] * fA2 + mat[15] * fA0, 514 - mat[ 8] * fA4 + mat[ 9] * fA2 - mat[11] * fA0, 515 - mat[ 4] * fB3 + mat[ 5] * fB1 - mat[ 6] * fB0, 516 mat[ 0] * fB3 - mat[ 1] * fB1 + mat[ 2] * fB0, 517 - mat[12] * fA3 + mat[13] * fA1 - mat[14] * fA0, 518 mat[ 8] * fA3 - mat[ 9] * fA1 + mat[10] * fA0]; 519 520 return k; 521 } 522 523 c3dl.debug.logWarning('matrixAdjoint() called with a parameter that is not a proper Matrix'); 524 return null; 525 } 526 527 528 /** 529 Multiply a given Matrix 'mat' with a scalar value. This will result 530 in a matrix which has each component in 'mat' multiplied with 'scalar'. 531 532 @param {Array} mat The matrix to "scale". 533 @param {float} scalar The value which will be multiplied by each 534 component of 'mat'. 535 536 @returns {Array} The Matrix 'mat', with each component 537 multiplied by 'scalar'. 538 */ 539 c3dl.multiplyMatrixByScalar = function(mat, scalar) 540 { 541 var matrix = []; 542 543 if (c3dl.isValidMatrix(mat) && !isNaN(scalar)) 544 { 545 // Multiply each variable 546 for (var i = 0; i < 16; i++) 547 { 548 matrix[i] = mat[i] * scalar; 549 } 550 551 return matrix; 552 } 553 554 c3dl.debug.logWarning('multiplyMatrixByScalar() called with a parameters that are invalid'); 555 return null; 556 } 557 558 // ----------------------------------------------------------------------------- 559 560 561 /** 562 Divide a Matrix 'mat' by a scalar value. This will divide each 563 component of the matrix 'mat' by 'scalar' and reutrn the value. 564 565 @param {Array} mat The matrix which will be divided. 566 @param {float} scalar The value which the matrix components 567 will be divided by. 568 569 @returns {Array} The Matrix 'mat' divided by 'scalar'. 570 */ 571 c3dl.divideMatrixByScalar = function(mat, scalar) 572 { 573 var matrix = []; 574 575 if (c3dl.isValidMatrix(mat) && !isNaN(scalar) && scalar != 0.0) 576 { 577 // Multiply each variable 578 for (var i = 0; i < 16; i++) 579 { 580 matrix[i] = mat[i] / scalar; 581 } 582 583 return matrix; 584 } 585 586 c3dl.debug.logWarning('multiplyMatrixByScalar() called with a parameters that are invalid'); 587 return null; 588 } 589 590 591 /** 592 Multiply matrix 'matOne' by 'matTwo'. 593 594 @param {Array} matOne 595 @param {Array} matTwo 596 597 @returns {Array} The result of multiplying 'matOne' by 'matTwo'. 598 */ 599 c3dl.multiplyMatrixByMatrix = function(matOne, matTwo, newMat) 600 { 601 if (!newMat) 602 { 603 newMat = []; 604 } 605 606 // Check to see if the value being passed is a Matrix 607 if (!c3dl.isValidMatrix(matOne) || !c3dl.isValidMatrix(matTwo)) 608 { 609 c3dl.debug.logWarning('multiplyMatrixByMatrix() called with a invalid parameters'); 610 return null; 611 } 612 613 // We multiply the first by the second 614 newMat[ 0] = (matOne[ 0] * matTwo[ 0] + matOne[ 4] * matTwo[ 1] + matOne[ 8] * matTwo[ 2] + matOne[12] * matTwo[ 3]); 615 newMat[ 1] = (matOne[ 1] * matTwo[ 0] + matOne[ 5] * matTwo[ 1] + matOne[ 9] * matTwo[ 2] + matOne[13] * matTwo[ 3]); 616 newMat[ 2] = (matOne[ 2] * matTwo[ 0] + matOne[ 6] * matTwo[ 1] + matOne[10] * matTwo[ 2] + matOne[14] * matTwo[ 3]); 617 newMat[ 3] = (matOne[ 3] * matTwo[ 0] + matOne[ 7] * matTwo[ 1] + matOne[11] * matTwo[ 2] + matOne[15] * matTwo[ 3]); 618 619 newMat[ 4] = (matOne[ 0] * matTwo[ 4] + matOne[ 4] * matTwo[ 5] + matOne[ 8] * matTwo[ 6] + matOne[12] * matTwo[ 7]); 620 newMat[ 5] = (matOne[ 1] * matTwo[ 4] + matOne[ 5] * matTwo[ 5] + matOne[ 9] * matTwo[ 6] + matOne[13] * matTwo[ 7]); 621 newMat[ 6] = (matOne[ 2] * matTwo[ 4] + matOne[ 6] * matTwo[ 5] + matOne[10] * matTwo[ 6] + matOne[14] * matTwo[ 7]); 622 newMat[ 7] = (matOne[ 3] * matTwo[ 4] + matOne[ 7] * matTwo[ 5] + matOne[11] * matTwo[ 6] + matOne[15] * matTwo[ 7]); 623 624 newMat[ 8] = (matOne[ 0] * matTwo[ 8] + matOne[ 4] * matTwo[ 9] + matOne[ 8] * matTwo[10] + matOne[12] * matTwo[11]); 625 newMat[ 9] = (matOne[ 1] * matTwo[ 8] + matOne[ 5] * matTwo[ 9] + matOne[ 9] * matTwo[10] + matOne[13] * matTwo[11]); 626 newMat[10] = (matOne[ 2] * matTwo[ 8] + matOne[ 6] * matTwo[ 9] + matOne[10] * matTwo[10] + matOne[14] * matTwo[11]); 627 newMat[11] = (matOne[ 3] * matTwo[ 8] + matOne[ 7] * matTwo[ 9] + matOne[11] * matTwo[10] + matOne[15] * matTwo[11]); 628 629 newMat[12] = (matOne[ 0] * matTwo[12] + matOne[ 4] * matTwo[13] + matOne[ 8] * matTwo[14] + matOne[12] * matTwo[15]); 630 newMat[13] = (matOne[ 1] * matTwo[12] + matOne[ 5] * matTwo[13] + matOne[ 9] * matTwo[14] + matOne[13] * matTwo[15]); 631 newMat[14] = (matOne[ 2] * matTwo[12] + matOne[ 6] * matTwo[13] + matOne[10] * matTwo[14] + matOne[14] * matTwo[15]); 632 newMat[15] = (matOne[ 3] * matTwo[12] + matOne[ 7] * matTwo[13] + matOne[11] * matTwo[14] + matOne[15] * matTwo[15]); 633 634 if (c3dl.isValidMatrix(newMat)) 635 { 636 return newMat; 637 } 638 else 639 { 640 c3dl.debug.logWarning('multiplyMatrixByMatrix() matrix multiplication error'); 641 return null; 642 } 643 } 644 645 646 /** 647 Multiply a matrix by a direction vector 648 649 @param {Array} mat 650 @param {Array} vec 651 @param {Array} dest 652 653 @returns {Array} vector 654 */ 655 c3dl.multiplyMatrixByDirection = function(mat, vec, dest) 656 { 657 if (c3dl.isValidMatrix(mat) && c3dl.isValidVector(vec)) 658 { 659 if (!dest) 660 { 661 dest = c3dl.makeVector(); 662 663 // since we don't need to multiply the translation part, we leave it out. 664 dest[0] = mat[ 0] * vec[0] + mat[ 4] * vec[1] + mat[ 8] * vec[2];// + mat[12] * 0; 665 dest[1] = mat[ 1] * vec[0] + mat[ 5] * vec[1] + mat[ 9] * vec[2];// + mat[13] * 0; 666 dest[2] = mat[ 2] * vec[0] + mat[ 6] * vec[1] + mat[10] * vec[2];// + mat[14] * 0; 667 668 return dest; 669 } 670 else 671 { 672 var a = mat[ 0] * vec[0] + mat[ 4] * vec[1] + mat[ 8] * vec[2];// + mat[12] * 0; 673 var b = mat[ 1] * vec[0] + mat[ 5] * vec[1] + mat[ 9] * vec[2];// + mat[13] * 0; 674 var c = mat[ 2] * vec[0] + mat[ 6] * vec[1] + mat[10] * vec[2];// + mat[14] * 0; 675 676 dest[0] = a; 677 dest[1] = b; 678 dest[2] = c; 679 680 return dest; 681 } 682 } 683 dest = null; 684 c3dl.debug.logWarning('multiplyMatrixByDirection() called with invalid parameters'); 685 return null; 686 } 687 688 689 /** 690 Multiply a vector 'vec' by Matrix 'mat'. This results in a vector 691 which the elements are found by calculatig the dot product of the 692 column vectors of 'mat' by 'vec'. 693 694 If 'vec' is an array of 3 values, the last component, w will be assumed to be 1. If 'vec' 695 is an array of 4 values, dest must also be an array of 4 values. 696 697 @param {Array} mat The matrix, an array of 16 values. 698 699 @param {Array} vec Array of 3 or 4 values. If last component, W is not present, W=1 will 700 be assumed. Also, if the Array has 3 elements, the return value will be 3 elements. If the 701 array has 4 elements, the return value will have 4 elements. 702 703 @param {Array} dest Optional return by reference. 704 705 @returns {Array} The vector 'vec' multiplied by matrix 'mat' if both 706 arguments were valid, otherwise returns null. 707 */ 708 c3dl.multiplyMatrixByVector = function(mat, vec, dest) 709 { 710 if (c3dl.isValidMatrix(mat) && c3dl.isValidVector(vec)) 711 { 712 // if user didn't give us last component, assume 1 which is the majority 713 // of the cases. 714 var w = (vec.length == 3 ? 1 : vec[3]); 715 716 if (!dest) 717 { 718 // match the destination size with the vector size. 719 dest = (vec.length == 3 ? [0,0,0] : [0,0,0,0]); 720 721 dest[0] = mat[ 0] * vec[0] + mat[ 4] * vec[1] + mat[ 8] * vec[2] + mat[12] * w; 722 dest[1] = mat[ 1] * vec[0] + mat[ 5] * vec[1] + mat[ 9] * vec[2] + mat[13] * w; 723 dest[2] = mat[ 2] * vec[0] + mat[ 6] * vec[1] + mat[10] * vec[2] + mat[14] * w; 724 725 // only write to the 4th component if it actually exists 726 if( dest.length == 4 ) 727 { 728 dest[3] = mat[ 3] * vec[0] + mat[ 7] * vec[1] + mat[11] * vec[2] + mat[15] * w; 729 } 730 731 return dest; 732 } 733 else 734 { 735 var a = mat[ 0] * vec[0] + mat[ 4] * vec[1] + mat[ 8] * vec[2] + mat[12] * w; 736 var b = mat[ 1] * vec[0] + mat[ 5] * vec[1] + mat[ 9] * vec[2] + mat[13] * w; 737 var c = mat[ 2] * vec[0] + mat[ 6] * vec[1] + mat[10] * vec[2] + mat[14] * w; 738 var d = mat[ 3] * vec[0] + mat[ 7] * vec[1] + mat[11] * vec[2] + mat[15] * w; 739 740 dest[0] = a; 741 dest[1] = b; 742 dest[2] = c; 743 744 // make sure they passed us a 4 component vector before trying to write to that 745 // element. 746 if(dest.length == 4) 747 { 748 dest[3] = d 749 } 750 751 return dest; 752 } 753 } 754 dest = null; 755 c3dl.debug.logWarning('multiplyMatrixByVector() called with invalid parameters'); 756 return null; 757 } 758 759 /** 760 Add two matrices. This will result in a matrix in which each 761 corresponding component of each matrix are added together. 762 763 @param {Array} matOne The first matrix. 764 @param {Array} matTwo The second matrix. 765 766 @returns {Array} A Matrix which is the addition of 'matOne' and 767 'matTwo'. 768 */ 769 c3dl.addMatrices = function(matOne, matTwo) 770 { 771 if (c3dl.isValidMatrix(matOne) && c3dl.isValidMatrix(matTwo)) 772 { 773 var m = []; 774 775 for (var i = 0; i < 16; i++) 776 { 777 // Add each value of the matrix to its counterpart 778 m[i] = matOne[i] + matTwo[i]; 779 } 780 781 return m; 782 } 783 784 c3dl.debug.logWarning('addMatrices() called with invalid parameters'); 785 return null; 786 } 787 788 789 /** 790 Subtract Matrix 'matTwo' from 'matOne'. This will result in a 791 matrix in which each component of 'matTwo' is subtracted from 792 Matrix 'matOne. 793 794 @param {Array} matOne The matrix which is being 795 subtracted from. 796 @param {Array} matTwo The matrix which is matOne is being 797 subtracted from. 798 799 @returns {Array} A matrix which is 'matTwo' subtracted from 'matOne'. 800 */ 801 c3dl.subtractMatrices = function(matOne, matTwo) 802 { 803 if (c3dl.isValidMatrix(matOne) && c3dl.isValidMatrix(matTwo)) 804 { 805 var m = []; 806 807 for (var i = 0; i < 16; i++) 808 { 809 // Add each value of the matrix to its counterpart 810 m[i] = matOne[i] - matTwo[i]; 811 } 812 813 return m; 814 } 815 816 c3dl.debug.logWarning('subtractMatrices() called with invalid parameters'); 817 return null; 818 } 819