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