PageSourceSearch

http://www.learnopengles.com/wordpress/wp-content/uploads/2011/06/glMatrix.js

js learnopengles.com collected 2026-10-02 05:13:22 UTC 42,059 bytes, 1,834 lines download raw bytes

1/* 
2 * glMatrix.js - High performance matrix and vector operations for WebGL
3 * version 0.9.6
4 */
5 
6/*
7 * Copyright (c) 2011 Brandon Jones
8 *
9 * This software is provided 'as-is', without any express or implied
10 * warranty. In no event will the authors be held liable for any damages
11 * arising from the use of this software.
12 *
13 * Permission is granted to anyone to use this software for any purpose,
14 * including commercial applications, and to alter it and redistribute it
15 * freely, subject to the following restrictions:
16 *
17 *    1. The origin of this software must not be misrepresented; you must not
18 *    claim that you wrote the original software. If you use this software
19 *    in a product, an acknowledgment in the product documentation would be
20 *    appreciated but is not required.
21 *
22 *    2. Altered source versions must be plainly marked as such, and must not
23 *    be misrepresented as being the original software.
24 *
25 *    3. This notice may not be removed or altered from any source
26 *    distribution.
27 */
28
29// Fallback for systems that don't support WebGL
30if(typeof Float32Array != 'undefined') {
31	glMatrixArrayType = Float32Array;
32} else if(typeof WebGLFloatArray != 'undefined') {
33	glMatrixArrayType = WebGLFloatArray; // This is officially deprecated and should dissapear in future revisions.
34} else {
35	glMatrixArrayType = Array;
36}
37
38/*
39 * vec3 - 3 Dimensional Vector
40 */
41var vec3 = {};
42
43/*
44 * vec3.create
45 * Creates a new instance of a vec3 using the default array type
46 * Any javascript array containing at least 3 numeric elements can serve as a vec3
47 *
48 * Params:
49 * vec - Optional, vec3 containing values to initialize with
50 *
51 * Returns:
52 * New vec3
53 */
54vec3.create = function(vec) {
55	var dest = new glMatrixArrayType(3);
56	
57	if(vec) {
58		dest[0] = vec[0];
59		dest[1] = vec[1];
60		dest[2] = vec[2];
61	}
62	
63	return dest;
64};
65
66/*
67 * vec3.set
68 * Copies the values of one vec3 to another
69 *
70 * Params:
71 * vec - vec3 containing values to copy
72 * dest - vec3 receiving copied values
73 *
74 * Returns:
75 * dest
76 */
77vec3.set = function(vec, dest) {
78	dest[0] = vec[0];
79	dest[1] = vec[1];
80	dest[2] = vec[2];
81	
82	return dest;
83};
84
85/*
86 * vec3.add
87 * Performs a vector addition
88 *
89 * Params:
90 * vec - vec3, first operand
91 * vec2 - vec3, second operand
92 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
93 *
94 * Returns:
95 * dest if specified, vec otherwise
96 */
97vec3.add = function(vec, vec2, dest) {
98	if(!dest || vec == dest) {
99		vec[0] += vec2[0];
100		vec[1] += vec2[1];
101		vec[2] += vec2[2];
102		return vec;
103	}
104	
105	dest[0] = vec[0] + vec2[0];
106	dest[1] = vec[1] + vec2[1];
107	dest[2] = vec[2] + vec2[2];
108	return dest;
109};
110
111/*
112 * vec3.subtract
113 * Performs a vector subtraction
114 *
115 * Params:
116 * vec - vec3, first operand
117 * vec2 - vec3, second operand
118 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
119 *
120 * Returns:
121 * dest if specified, vec otherwise
122 */
123vec3.subtract = function(vec, vec2, dest) {
124	if(!dest || vec == dest) {
125		vec[0] -= vec2[0];
126		vec[1] -= vec2[1];
127		vec[2] -= vec2[2];
128		return vec;
129	}
130	
131	dest[0] = vec[0] - vec2[0];
132	dest[1] = vec[1] - vec2[1];
133	dest[2] = vec[2] - vec2[2];
134	return dest;
135};
136
137/*
138 * vec3.negate
139 * Negates the components of a vec3
140 *
141 * Params:
142 * vec - vec3 to negate
143 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
144 *
145 * Returns:
146 * dest if specified, vec otherwise
147 */
148vec3.negate = function(vec, dest) {
149	if(!dest) { dest = vec; }
150	
151	dest[0] = -vec[0];
152	dest[1] = -vec[1];
153	dest[2] = -vec[2];
154	return dest;
155};
156
157/*
158 * vec3.scale
159 * Multiplies the components of a vec3 by a scalar value
160 *
161 * Params:
162 * vec - vec3 to scale
163 * val - Numeric value to scale by
164 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
165 *
166 * Returns:
167 * dest if specified, vec otherwise
168 */
169vec3.scale = function(vec, val, dest) {
170	if(!dest || vec == dest) {
171		vec[0] *= val;
172		vec[1] *= val;
173		vec[2] *= val;
174		return vec;
175	}
176	
177	dest[0] = vec[0]*val;
178	dest[1] = vec[1]*val;
179	dest[2] = vec[2]*val;
180	return dest;
181};
182
183/*
184 * vec3.normalize
185 * Generates a unit vector of the same direction as the provided vec3
186 * If vector length is 0, returns [0, 0, 0]
187 *
188 * Params:
189 * vec - vec3 to normalize
190 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
191 *
192 * Returns:
193 * dest if specified, vec otherwise
194 */
195vec3.normalize = function(vec, dest) {
196	if(!dest) { dest = vec; }
197	
198	var x = vec[0], y = vec[1], z = vec[2];
199	var len = Math.sqrt(x*x + y*y + z*z);
200	
201	if (!len) {
202		dest[0] = 0;
203		dest[1] = 0;
204		dest[2] = 0;
205		return dest;
206	} else if (len == 1) {
207		dest[0] = x;
208		dest[1] = y;
209		dest[2] = z;
210		return dest;
211	}
212	
213	len = 1 / len;
214	dest[0] = x*len;
215	dest[1] = y*len;
216	dest[2] = z*len;
217	return dest;
218};
219
220/*
221 * vec3.cross
222 * Generates the cross product of two vec3s
223 *
224 * Params:
225 * vec - vec3, first operand
226 * vec2 - vec3, second operand
227 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
228 *
229 * Returns:
230 * dest if specified, vec otherwise
231 */
232vec3.cross = function(vec, vec2, dest){
233	if(!dest) { dest = vec; }
234	
235	var x = vec[0], y = vec[1], z = vec[2];
236	var x2 = vec2[0], y2 = vec2[1], z2 = vec2[2];
237	
238	dest[0] = y*z2 - z*y2;
239	dest[1] = z*x2 - x*z2;
240	dest[2] = x*y2 - y*x2;
241	return dest;
242};
243
244/*
245 * vec3.length
246 * Caclulates the length of a vec3
247 *
248 * Params:
249 * vec - vec3 to calculate length of
250 *
251 * Returns:
252 * Length of vec
253 */
254vec3.length = function(vec){
255	var x = vec[0], y = vec[1], z = vec[2];
256	return Math.sqrt(x*x + y*y + z*z);
257};
258
259/*
260 * vec3.dot
261 * Caclulates the dot product of two vec3s
262 *
263 * Params:
264 * vec - vec3, first operand
265 * vec2 - vec3, second operand
266 *
267 * Returns:
268 * Dot product of vec and vec2
269 */
270vec3.dot = function(vec, vec2){
271	return vec[0]*vec2[0] + vec[1]*vec2[1] + vec[2]*vec2[2];
272};
273
274/*
275 * vec3.direction
276 * Generates a unit vector pointing from one vector to another
277 *
278 * Params:
279 * vec - origin vec3
280 * vec2 - vec3 to point to
281 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
282 *
283 * Returns:
284 * dest if specified, vec otherwise
285 */
286vec3.direction = function(vec, vec2, dest) {
287	if(!dest) { dest = vec; }
288	
289	var x = vec[0] - vec2[0];
290	var y = vec[1] - vec2[1];
291	var z = vec[2] - vec2[2];
292	
293	var len = Math.sqrt(x*x + y*y + z*z);
294	if (!len) { 
295		dest[0] = 0; 
296		dest[1] = 0; 
297		dest[2] = 0;
298		return dest; 
299	}
300	
301	len = 1 / len;
302	dest[0] = x * len; 
303	dest[1] = y * len; 
304	dest[2] = z * len;
305	return dest; 
306};
307
308/*
309 * vec3.lerp
310 * Performs a linear interpolation between two vec3
311 *
312 * Params:
313 * vec - vec3, first vector
314 * vec2 - vec3, second vector
315 * lerp - interpolation amount between the two inputs
316 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
317 *
318 * Returns:
319 * dest if specified, vec otherwise
320 */
321vec3.lerp = function(vec, vec2, lerp, dest){
322    if(!dest) { dest = vec; }
323    
324    dest[0] = vec[0] + lerp * (vec2[0] - vec[0]);
325    dest[1] = vec[1] + lerp * (vec2[1] - vec[1]);
326    dest[2] = vec[2] + lerp * (vec2[2] - vec[2]);
327    
328    return dest;
329}
330
331/*
332 * vec3.str
333 * Returns a string representation of a vector
334 *
335 * Params:
336 * vec - vec3 to represent as a string
337 *
338 * Returns:
339 * string representation of vec
340 */
341vec3.str = function(vec) {
342	return '[' + vec[0] + ', ' + vec[1] + ', ' + vec[2] + ']'; 
343};
344
345/*
346 * mat3 - 3x3 Matrix
347 */
348var mat3 = {};
349
350/*
351 * mat3.create
352 * Creates a new instance of a mat3 using the default array type
353 * Any javascript array containing at least 9 numeric elements can serve as a mat3
354 *
355 * Params:
356 * mat - Optional, mat3 containing values to initialize with
357 *
358 * Returns:
359 * New mat3
360 */
361mat3.create = function(mat) {
362	var dest = new glMatrixArrayType(9);
363	
364	if(mat) {
365		dest[0] = mat[0];
366		dest[1] = mat[1];
367		dest[2] = mat[2];
368		dest[3] = mat[3];
369		dest[4] = mat[4];
370		dest[5] = mat[5];
371		dest[6] = mat[6];
372		dest[7] = mat[7];
373		dest[8] = mat[8];
374	}
375	
376	return dest;
377};
378
379/*
380 * mat3.set
381 * Copies the values of one mat3 to another
382 *
383 * Params:
384 * mat - mat3 containing values to copy
385 * dest - mat3 receiving copied values
386 *
387 * Returns:
388 * dest
389 */
390mat3.set = function(mat, dest) {
391	dest[0] = mat[0];
392	dest[1] = mat[1];
393	dest[2] = mat[2];
394	dest[3] = mat[3];
395	dest[4] = mat[4];
396	dest[5] = mat[5];
397	dest[6] = mat[6];
398	dest[7] = mat[7];
399	dest[8] = mat[8];
400	return dest;
401};
402
403/*
404 * mat3.identity
405 * Sets a mat3 to an identity matrix
406 *
407 * Params:
408 * dest - mat3 to set
409 *
410 * Returns:
411 * dest
412 */
413mat3.identity = function(dest) {
414	dest[0] = 1;
415	dest[1] = 0;
416	dest[2] = 0;
417	dest[3] = 0;
418	dest[4] = 1;
419	dest[5] = 0;
420	dest[6] = 0;
421	dest[7] = 0;
422	dest[8] = 1;
423	return dest;
424};
425
426/*
427 * mat4.transpose
428 * Transposes a mat3 (flips the values over the diagonal)
429 *
430 * Params:
431 * mat - mat3 to transpose
432 * dest - Optional, mat3 receiving transposed values. If not specified result is written to mat
433 *
434 * Returns:
435 * dest is specified, mat otherwise
436 */
437mat3.transpose = function(mat, dest) {
438	// If we are transposing ourselves we can skip a few steps but have to cache some values
439	if(!dest || mat == dest) { 
440		var a01 = mat[1], a02 = mat[2];
441		var a12 = mat[5];
442		
443        mat[1] = mat[3];
444        mat[2] = mat[6];
445        mat[3] = a01;
446        mat[5] = mat[7];
447        mat[6] = a02;
448        mat[7] = a12;
449		return mat;
450	}
451	
452	dest[0] = mat[0];
453	dest[1] = mat[3];
454	dest[2] = mat[6];
455	dest[3] = mat[1];
456	dest[4] = mat[4];
457	dest[5] = mat[7];
458	dest[6] = mat[2];
459	dest[7] = mat[5];
460	dest[8] = mat[8];
461	return dest;
462};
463
464/*
465 * mat3.toMat4
466 * Copies the elements of a mat3 into the upper 3x3 elements of a mat4
467 *
468 * Params:
469 * mat - mat3 containing values to copy
470 * dest - Optional, mat4 receiving copied values
471 *
472 * Returns:
473 * dest if specified, a new mat4 otherwise
474 */
475mat3.toMat4 = function(mat, dest) {
476	if(!dest) { dest = mat4.create(); }
477	
478	dest[0] = mat[0];
479	dest[1] = mat[1];
480	dest[2] = mat[2];
481	dest[3] = 0;
482
483	dest[4] = mat[3];
484	dest[5] = mat[4];
485	dest[6] = mat[5];
486	dest[7] = 0;
487
488	dest[8] = mat[6];
489	dest[9] = mat[7];
490	dest[10] = mat[8];
491	dest[11] = 0;
492
493	dest[12] = 0;
494	dest[13] = 0;
495	dest[14] = 0;
496	dest[15] = 1;
497	
498	return dest;
499}
500
501/*
502 * mat3.str
503 * Returns a string representation of a mat3
504 *
505 * Params:
506 * mat - mat3 to represent as a string
507 *
508 * Returns:
509 * string representation of mat
510 */
511mat3.str = function(mat) {
512	return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + 
513		', ' + mat[3] + ', '+ mat[4] + ', ' + mat[5] + 
514		', ' + mat[6] + ', ' + mat[7] + ', '+ mat[8] + ']';
515};
516
517/*
518 * mat4 - 4x4 Matrix
519 */
520var mat4 = {};
521
522/*
523 * mat4.create
524 * Creates a new instance of a mat4 using the default array type
525 * Any javascript array containing at least 16 numeric elements can serve as a mat4
526 *
527 * Params:
528 * mat - Optional, mat4 containing values to initialize with
529 *
530 * Returns:
531 * New mat4
532 */
533mat4.create = function(mat) {
534	var dest = new glMatrixArrayType(16);
535	
536	if(mat) {
537		dest[0] = mat[0];
538		dest[1] = mat[1];
539		dest[2] = mat[2];
540		dest[3] = mat[3];
541		dest[4] = mat[4];
542		dest[5] = mat[5];
543		dest[6] = mat[6];
544		dest[7] = mat[7];
545		dest[8] = mat[8];
546		dest[9] = mat[9];
547		dest[10] = mat[10];
548		dest[11] = mat[11];
549		dest[12] = mat[12];
550		dest[13] = mat[13];
551		dest[14] = mat[14];
552		dest[15] = mat[15];
553	}
554	
555	return dest;
556};
557
558/*
559 * mat4.set
560 * Copies the values of one mat4 to another
561 *
562 * Params:
563 * mat - mat4 containing values to copy
564 * dest - mat4 receiving copied values
565 *
566 * Returns:
567 * dest
568 */
569mat4.set = function(mat, dest) {
570	dest[0] = mat[0];
571	dest[1] = mat[1];
572	dest[2] = mat[2];
573	dest[3] = mat[3];
574	dest[4] = mat[4];
575	dest[5] = mat[5];
576	dest[6] = mat[6];
577	dest[7] = mat[7];
578	dest[8] = mat[8];
579	dest[9] = mat[9];
580	dest[10] = mat[10];
581	dest[11] = mat[11];
582	dest[12] = mat[12];
583	dest[13] = mat[13];
584	dest[14] = mat[14];
585	dest[15] = mat[15];
586	return dest;
587};
588
589/*
590 * mat4.identity
591 * Sets a mat4 to an identity matrix
592 *
593 * Params:
594 * dest - mat4 to set
595 *
596 * Returns:
597 * dest
598 */
599mat4.identity = function(dest) {
600	dest[0] = 1;
601	dest[1] = 0;
602	dest[2] = 0;
603	dest[3] = 0;
604	dest[4] = 0;
605	dest[5] = 1;
606	dest[6] = 0;
607	dest[7] = 0;
608	dest[8] = 0;
609	dest[9] = 0;
610	dest[10] = 1;
611	dest[11] = 0;
612	dest[12] = 0;
613	dest[13] = 0;
614	dest[14] = 0;
615	dest[15] = 1;
616	return dest;
617};
618
619/*
620 * mat4.transpose
621 * Transposes a mat4 (flips the values over the diagonal)
622 *
623 * Params:
624 * mat - mat4 to transpose
625 * dest - Optional, mat4 receiving transposed values. If not specified result is written to mat
626 *
627 * Returns:
628 * dest is specified, mat otherwise
629 */
630mat4.transpose = function(mat, dest) {
631	// If we are transposing ourselves we can skip a few steps but have to cache some values
632	if(!dest || mat == dest) { 
633		var a01 = mat[1], a02 = mat[2], a03 = mat[3];
634		var a12 = mat[6], a13 = mat[7];
635		var a23 = mat[11];
636		
637		mat[1] = mat[4];
638		mat[2] = mat[8];
639		mat[3] = mat[12];
640		mat[4] = a01;
641		mat[6] = mat[9];
642		mat[7] = mat[13];
643		mat[8] = a02;
644		mat[9] = a12;
645		mat[11] = mat[14];
646		mat[12] = a03;
647		mat[13] = a13;
648		mat[14] = a23;
649		return mat;
650	}
651	
652	dest[0] = mat[0];
653	dest[1] = mat[4];
654	dest[2] = mat[8];
655	dest[3] = mat[12];
656	dest[4] = mat[1];
657	dest[5] = mat[5];
658	dest[6] = mat[9];
659	dest[7] = mat[13];
660	dest[8] = mat[2];
661	dest[9] = mat[6];
662	dest[10] = mat[10];
663	dest[11] = mat[14];
664	dest[12] = mat[3];
665	dest[13] = mat[7];
666	dest[14] = mat[11];
667	dest[15] = mat[15];
668	return dest;
669};
670
671/*
672 * mat4.determinant
673 * Calculates the determinant of a mat4
674 *
675 * Params:
676 * mat - mat4 to calculate determinant of
677 *
678 * Returns:
679 * determinant of mat
680 */
681mat4.determinant = function(mat) {
682	// Cache the matrix values (makes for huge speed increases!)
683	var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
684	var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
685	var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11];
686	var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
687
688	return	a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +
689			a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +
690			a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +
691			a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +
692			a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +
693			a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
694};
695
696/*
697 * mat4.inverse
698 * Calculates the inverse matrix of a mat4
699 *
700 * Params:
701 * mat - mat4 to calculate inverse of
702 * dest - Optional, mat4 receiving inverse matrix. If not specified result is written to mat
703 *
704 * Returns:
705 * dest is specified, mat otherwise
706 */
707mat4.inverse = function(mat, dest) {
708	if(!dest) { dest = mat; }
709	
710	// Cache the matrix values (makes for huge speed increases!)
711	var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
712	var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
713	var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11];
714	var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
715	
716	var b00 = a00*a11 - a01*a10;
717	var b01 = a00*a12 - a02*a10;
718	var b02 = a00*a13 - a03*a10;
719	var b03 = a01*a12 - a02*a11;
720	var b04 = a01*a13 - a03*a11;
721	var b05 = a02*a13 - a03*a12;
722	var b06 = a20*a31 - a21*a30;
723	var b07 = a20*a32 - a22*a30;
724	var b08 = a20*a33 - a23*a30;
725	var b09 = a21*a32 - a22*a31;
726	var b10 = a21*a33 - a23*a31;
727	var b11 = a22*a33 - a23*a32;
728	
729	// Calculate the determinant (inlined to avoid double-caching)
730	var invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
731	
732	dest[0] = (a11*b11 - a12*b10 + a13*b09)*invDet;
733	dest[1] = (-a01*b11 + a02*b10 - a03*b09)*invDet;
734	dest[2] = (a31*b05 - a32*b04 + a33*b03)*invDet;
735	dest[3] = (-a21*b05 + a22*b04 - a23*b03)*invDet;
736	dest[4] = (-a10*b11 + a12*b08 - a13*b07)*invDet;
737	dest[5] = (a00*b11 - a02*b08 + a03*b07)*invDet;
738	dest[6] = (-a30*b05 + a32*b02 - a33*b01)*invDet;
739	dest[7] = (a20*b05 - a22*b02 + a23*b01)*invDet;
740	dest[8] = (a10*b10 - a11*b08 + a13*b06)*invDet;
741	dest[9] = (-a00*b10 + a01*b08 - a03*b06)*invDet;
742	dest[10] = (a30*b04 - a31*b02 + a33*b00)*invDet;
743	dest[11] = (-a20*b04 + a21*b02 - a23*b00)*invDet;
744	dest[12] = (-a10*b09 + a11*b07 - a12*b06)*invDet;
745	dest[13] = (a00*b09 - a01*b07 + a02*b06)*invDet;
746	dest[14] = (-a30*b03 + a31*b01 - a32*b00)*invDet;
747	dest[15] = (a20*b03 - a21*b01 + a22*b00)*invDet;
748	
749	return dest;
750};
751
752/*
753 * mat4.toRotationMat
754 * Copies the upper 3x3 elements of a mat4 into another mat4
755 *
756 * Params:
757 * mat - mat4 containing values to copy
758 * dest - Optional, mat4 receiving copied values
759 *
760 * Returns:
761 * dest is specified, a new mat4 otherwise
762 */
763mat4.toRotationMat = function(mat, dest) {
764	if(!dest) { dest = mat4.create(); }
765	
766	dest[0] = mat[0];
767	dest[1] = mat[1];
768	dest[2] = mat[2];
769	dest[3] = mat[3];
770	dest[4] = mat[4];
771	dest[5] = mat[5];
772	dest[6] = mat[6];
773	dest[7] = mat[7];
774	dest[8] = mat[8];
775	dest[9] = mat[9];
776	dest[10] = mat[10];
777	dest[11] = mat[11];
778	dest[12] = 0;
779	dest[13] = 0;
780	dest[14] = 0;
781	dest[15] = 1;
782	
783	return dest;
784};
785
786/*
787 * mat4.toMat3
788 * Copies the upper 3x3 elements of a mat4 into a mat3
789 *
790 * Params:
791 * mat - mat4 containing values to copy
792 * dest - Optional, mat3 receiving copied values
793 *
794 * Returns:
795 * dest is specified, a new mat3 otherwise
796 */
797mat4.toMat3 = function(mat, dest) {
798	if(!dest) { dest = mat3.create(); }
799	
800	dest[0] = mat[0];
801	dest[1] = mat[1];
802	dest[2] = mat[2];
803	dest[3] = mat[4];
804	dest[4] = mat[5];
805	dest[5] = mat[6];
806	dest[6] = mat[8];
807	dest[7] = mat[9];
808	dest[8] = mat[10];
809	
810	return dest;
811};
812
813/*
814 * mat4.toInverseMat3
815 * Calculates the inverse of the upper 3x3 elements of a mat4 and copies the result into a mat3
816 * The resulting matrix is useful for calculating transformed normals
817 *
818 * Params:
819 * mat - mat4 containing values to invert and copy
820 * dest - Optional, mat3 receiving values
821 *
822 * Returns:
823 * dest is specified, a new mat3 otherwise
824 */
825mat4.toInverseMat3 = function(mat, dest) {
826	// Cache the matrix values (makes for huge speed increases!)
827	var a00 = mat[0], a01 = mat[1], a02 = mat[2];
828	var a10 = mat[4], a11 = mat[5], a12 = mat[6];
829	var a20 = mat[8], a21 = mat[9], a22 = mat[10];
830	
831	var b01 = a22*a11-a12*a21;
832	var b11 = -a22*a10+a12*a20;
833	var b21 = a21*a10-a11*a20;
834		
835	var d = a00*b01 + a01*b11 + a02*b21;
836	if (!d) { return null; }
837	var id = 1/d;
838	
839	if(!dest) { dest = mat3.create(); }
840	
841	dest[0] = b01*id;
842	dest[1] = (-a22*a01 + a02*a21)*id;
843	dest[2] = (a12*a01 - a02*a11)*id;
844	dest[3] = b11*id;
845	dest[4] = (a22*a00 - a02*a20)*id;
846	dest[5] = (-a12*a00 + a02*a10)*id;
847	dest[6] = b21*id;
848	dest[7] = (-a21*a00 + a01*a20)*id;
849	dest[8] = (a11*a00 - a01*a10)*id;
850	
851	return dest;
852};
853
854/*
855 * mat4.multiply
856 * Performs a matrix multiplication
857 *
858 * Params:
859 * mat - mat4, first operand
860 * mat2 - mat4, second operand
861 * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
862 *
863 * Returns:
864 * dest if specified, mat otherwise
865 */
866mat4.multiply = function(mat, mat2, dest) {
867	if(!dest) { dest = mat }
868	
869	// Cache the matrix values (makes for huge speed increases!)
870	var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
871	var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
872	var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11];
873	var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
874	
875	var b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3];
876	var b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7];
877	var b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11];
878	var b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15];
879	
880	dest[0] = b00*a00 + b01*a10 + b02*a20 + b03*a30;
881	dest[1] = b00*a01 + b01*a11 + b02*a21 + b03*a31;
882	dest[2] = b00*a02 + b01*a12 + b02*a22 + b03*a32;
883	dest[3] = b00*a03 + b01*a13 + b02*a23 + b03*a33;
884	dest[4] = b10*a00 + b11*a10 + b12*a20 + b13*a30;
885	dest[5] = b10*a01 + b11*a11 + b12*a21 + b13*a31;
886	dest[6] = b10*a02 + b11*a12 + b12*a22 + b13*a32;
887	dest[7] = b10*a03 + b11*a13 + b12*a23 + b13*a33;
888	dest[8] = b20*a00 + b21*a10 + b22*a20 + b23*a30;
889	dest[9] = b20*a01 + b21*a11 + b22*a21 + b23*a31;
890	dest[10] = b20*a02 + b21*a12 + b22*a22 + b23*a32;
891	dest[11] = b20*a03 + b21*a13 + b22*a23 + b23*a33;
892	dest[12] = b30*a00 + b31*a10 + b32*a20 + b33*a30;
893	dest[13] = b30*a01 + b31*a11 + b32*a21 + b33*a31;
894	dest[14] = b30*a02 + b31*a12 + b32*a22 + b33*a32;
895	dest[15] = b30*a03 + b31*a13 + b32*a23 + b33*a33;
896	
897	return dest;
898};
899
900/*
901 * mat4.multiplyVec3
902 * Transforms a vec3 with the given matrix
903 * 4th vector component is implicitly '1'
904 *
905 * Params:
906 * mat - mat4 to transform the vector with
907 * vec - vec3 to transform
908 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
909 *
910 * Returns:
911 * dest if specified, vec otherwise
912 */
913mat4.multiplyVec3 = function(mat, vec, dest) {
914	if(!dest) { dest = vec }
915	
916	var x = vec[0], y = vec[1], z = vec[2];
917	
918	dest[0] = mat[0]*x + mat[4]*y + mat[8]*z + mat[12];
919	dest[1] = mat[1]*x + mat[5]*y + mat[9]*z + mat[13];
920	dest[2] = mat[2]*x + mat[6]*y + mat[10]*z + mat[14];
921	
922	return dest;
923};
924
925/*
926 * mat4.multiplyVec4
927 * Transforms a vec4 with the given matrix
928 *
929 * Params:
930 * mat - mat4 to transform the vector with
931 * vec - vec4 to transform
932 * dest - Optional, vec4 receiving operation result. If not specified result is written to vec
933 *
934 * Returns:
935 * dest if specified, vec otherwise
936 */
937mat4.multiplyVec4 = function(mat, vec, dest) {
938	if(!dest) { dest = vec }
939	
940	var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
941	
942	dest[0] = mat[0]*x + mat[4]*y + mat[8]*z + mat[12]*w;
943	dest[1] = mat[1]*x + mat[5]*y + mat[9]*z + mat[13]*w;
944	dest[2] = mat[2]*x + mat[6]*y + mat[10]*z + mat[14]*w;
945	dest[3] = mat[3]*x + mat[7]*y + mat[11]*z + mat[15]*w;
946	
947	return dest;
948};
949
950/*
951 * mat4.translate
952 * Translates a matrix by the given vector
953 *
954 * Params:
955 * mat - mat4 to translate
956 * vec - vec3 specifying the translation
957 * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
958 *
959 * Returns:
960 * dest if specified, mat otherwise
961 */
962mat4.translate = function(mat, vec, dest) {
963	var x = vec[0], y = vec[1], z = vec[2];
964	
965	if(!dest || mat == dest) {
966		mat[12] = mat[0]*x + mat[4]*y + mat[8]*z + mat[12];
967		mat[13] = mat[1]*x + mat[5]*y + mat[9]*z + mat[13];
968		mat[14] = mat[2]*x + mat[6]*y + mat[10]*z + mat[14];
969		mat[15] = mat[3]*x + mat[7]*y + mat[11]*z + mat[15];
970		return mat;
971	}
972	
973	var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
974	var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
975	var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11];
976	
977	dest[0] = a00;
978	dest[1] = a01;
979	dest[2] = a02;
980	dest[3] = a03;
981	dest[4] = a10;
982	dest[5] = a11;
983	dest[6] = a12;
984	dest[7] = a13;
985	dest[8] = a20;
986	dest[9] = a21;
987	dest[10] = a22;
988	dest[11] = a23;
989	
990	dest[12] = a00*x + a10*y + a20*z + mat[12];
991	dest[13] = a01*x + a11*y + a21*z + mat[13];
992	dest[14] = a02*x + a12*y + a22*z + mat[14];
993	dest[15] = a03*x + a13*y + a23*z + mat[15];
994	return dest;
995};
996
997/*
998 * mat4.scale
999 * Scales a matrix by the given vector
1000 *
1001 * Params:
1002 * mat - mat4 to scale
1003 * vec - vec3 specifying the scale for each axis
1004 * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
1005 *
1006 * Returns:
1007 * dest if specified, mat otherwise
1008 */
1009mat4.scale = function(mat, vec, dest) {
1010	var x = vec[0], y = vec[1], z = vec[2];
1011	
1012	if(!dest || mat == dest) {
1013		mat[0] *= x;
1014		mat[1] *= x;
1015		mat[2] *= x;
1016		mat[3] *= x;
1017		mat[4] *= y;
1018		mat[5] *= y;
1019		mat[6] *= y;
1020		mat[7] *= y;
1021		mat[8] *= z;
1022		mat[9] *= z;
1023		mat[10] *= z;
1024		mat[11] *= z;
1025		return mat;
1026	}
1027	
1028	dest[0] = mat[0]*x;
1029	dest[1] = mat[1]*x;
1030	dest[2] = mat[2]*x;
1031	dest[3] = mat[3]*x;
1032	dest[4] = mat[4]*y;
1033	dest[5] = mat[5]*y;
1034	dest[6] = mat[6]*y;
1035	dest[7] = mat[7]*y;
1036	dest[8] = mat[8]*z;
1037	dest[9] = mat[9]*z;
1038	dest[10] = mat[10]*z;
1039	dest[11] = mat[11]*z;
1040	dest[12] = mat[12];
1041	dest[13] = mat[13];
1042	dest[14] = mat[14];
1043	dest[15] = mat[15];
1044	return dest;
1045};
1046
1047/*
1048 * mat4.rotate
1049 * Rotates a matrix by the given angle around the specified axis
1050 * If rotating around a primary axis (X,Y,Z) one of the specialized rotation functions should be used instead for performance
1051 *
1052 * Params:
1053 * mat - mat4 to rotate
1054 * angle - angle (in radians) to rotate
1055 * axis - vec3 representing the axis to rotate around 
1056 * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
1057 *
1058 * Returns:
1059 * dest if specified, mat otherwise
1060 */
1061mat4.rotate = function(mat, angle, axis, dest) {
1062	var x = axis[0], y = axis[1], z = axis[2];
1063	var len = Math.sqrt(x*x + y*y + z*z);
1064	if (!len) { return null; }
1065	if (len != 1) {
1066		len = 1 / len;
1067		x *= len; 
1068		y *= len; 
1069		z *= len;
1070	}
1071	
1072	var s = Math.sin(angle);
1073	var c = Math.cos(angle);
1074	var t = 1-c;
1075	
1076	// Cache the matrix values (makes for huge speed increases!)
1077	var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
1078	var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
1079	var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11];
1080	
1081	// Construct the elements of the rotation matrix
1082	var b00 = x*x*t + c, b01 = y*x*t + z*s, b02 = z*x*t - y*s;
1083	var b10 = x*y*t - z*s, b11 = y*y*t + c, b12 = z*y*t + x*s;
1084	var b20 = x*z*t + y*s, b21 = y*z*t - x*s, b22 = z*z*t + c;
1085	
1086	if(!dest) { 
1087		dest = mat 
1088	} else if(mat != dest) { // If the source and destination differ, copy the unchanged last row
1089		dest[12] = mat[12];
1090		dest[13] = mat[13];
1091		dest[14] = mat[14];
1092		dest[15] = mat[15];
1093	}
1094	
1095	// Perform rotation-specific matrix multiplication
1096	dest[0] = a00*b00 + a10*b01 + a20*b02;
1097	dest[1] = a01*b00 + a11*b01 + a21*b02;
1098	dest[2] = a02*b00 + a12*b01 + a22*b02;
1099	dest[3] = a03*b00 + a13*b01 + a23*b02;
1100	
1101	dest[4] = a00*b10 + a10*b11 + a20*b12;
1102	dest[5] = a01*b10 + a11*b11 + a21*b12;
1103	dest[6] = a02*b10 + a12*b11 + a22*b12;
1104	dest[7] = a03*b10 + a13*b11 + a23*b12;
1105	
1106	dest[8] = a00*b20 + a10*b21 + a20*b22;
1107	dest[9] = a01*b20 + a11*b21 + a21*b22;
1108	dest[10] = a02*b20 + a12*b21 + a22*b22;
1109	dest[11] = a03*b20 + a13*b21 + a23*b22;
1110	return dest;
1111};
1112
1113/*
1114 * mat4.rotateX
1115 * Rotates a matrix by the given angle around the X axis
1116 *
1117 * Params:
1118 * mat - mat4 to rotate
1119 * angle - angle (in radians) to rotate
1120 * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
1121 *
1122 * Returns:
1123 * dest if specified, mat otherwise
1124 */
1125mat4.rotateX = function(mat, angle, dest) {
1126	var s = Math.sin(angle);
1127	var c = Math.cos(angle);
1128	
1129	// Cache the matrix values (makes for huge speed increases!)
1130	var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
1131	var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11];
1132
1133	if(!dest) { 
1134		dest = mat 
1135	} else if(mat != dest) { // If the source and destination differ, copy the unchanged rows
1136		dest[0] = mat[0];
1137		dest[1] = mat[1];
1138		dest[2] = mat[2];
1139		dest[3] = mat[3];
1140		
1141		dest[12] = mat[12];
1142		dest[13] = mat[13];
1143		dest[14] = mat[14];
1144		dest[15] = mat[15];
1145	}
1146	
1147	// Perform axis-specific matrix multiplication
1148	dest[4] = a10*c + a20*s;
1149	dest[5] = a11*c + a21*s;
1150	dest[6] = a12*c + a22*s;
1151	dest[7] = a13*c + a23*s;
1152	
1153	dest[8] = a10*-s + a20*c;
1154	dest[9] = a11*-s + a21*c;
1155	dest[10] = a12*-s + a22*c;
1156	dest[11] = a13*-s + a23*c;
1157	return dest;
1158};
1159
1160/*
1161 * mat4.rotateY
1162 * Rotates a matrix by the given angle around the Y axis
1163 *
1164 * Params:
1165 * mat - mat4 to rotate
1166 * angle - angle (in radians) to rotate
1167 * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
1168 *
1169 * Returns:
1170 * dest if specified, mat otherwise
1171 */
1172mat4.rotateY = function(mat, angle, dest) {
1173	var s = Math.sin(angle);
1174	var c = Math.cos(angle);
1175	
1176	// Cache the matrix values (makes for huge speed increases!)
1177	var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
1178	var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11];
1179	
1180	if(!dest) { 
1181		dest = mat 
1182	} else if(mat != dest) { // If the source and destination differ, copy the unchanged rows
1183		dest[4] = mat[4];
1184		dest[5] = mat[5];
1185		dest[6] = mat[6];
1186		dest[7] = mat[7];
1187		
1188		dest[12] = mat[12];
1189		dest[13] = mat[13];
1190		dest[14] = mat[14];
1191		dest[15] = mat[15];
1192	}
1193	
1194	// Perform axis-specific matrix multiplication
1195	dest[0] = a00*c + a20*-s;
1196	dest[1] = a01*c + a21*-s;
1197	dest[2] = a02*c + a22*-s;
1198	dest[3] = a03*c + a23*-s;
1199	
1200	dest[8] = a00*s + a20*c;
1201	dest[9] = a01*s + a21*c;
1202	dest[10] = a02*s + a22*c;
1203	dest[11] = a03*s + a23*c;
1204	return dest;
1205};
1206
1207/*
1208 * mat4.rotateZ
1209 * Rotates a matrix by the given angle around the Z axis
1210 *
1211 * Params:
1212 * mat - mat4 to rotate
1213 * angle - angle (in radians) to rotate
1214 * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
1215 *
1216 * Returns:
1217 * dest if specified, mat otherwise
1218 */
1219mat4.rotateZ = function(mat, angle, dest) {
1220	var s = Math.sin(angle);
1221	var c = Math.cos(angle);
1222	
1223	// Cache the matrix values (makes for huge speed increases!)
1224	var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
1225	var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
1226	
1227	if(!dest) { 
1228		dest = mat 
1229	} else if(mat != dest) { // If the source and destination differ, copy the unchanged last row
1230		dest[8] = mat[8];
1231		dest[9] = mat[9];
1232		dest[10] = mat[10];
1233		dest[11] = mat[11];
1234		
1235		dest[12] = mat[12];
1236		dest[13] = mat[13];
1237		dest[14] = mat[14];
1238		dest[15] = mat[15];
1239	}
1240	
1241	// Perform axis-specific matrix multiplication
1242	dest[0] = a00*c + a10*s;
1243	dest[1] = a01*c + a11*s;
1244	dest[2] = a02*c + a12*s;
1245	dest[3] = a03*c + a13*s;
1246	
1247	dest[4] = a00*-s + a10*c;
1248	dest[5] = a01*-s + a11*c;
1249	dest[6] = a02*-s + a12*c;
1250	dest[7] = a03*-s + a13*c;
1251	
1252	return dest;
1253};
1254
1255/*
1256 * mat4.frustum
1257 * Generates a frustum matrix with the given bounds
1258 *
1259 * Params:
1260 * left, right - scalar, left and right bounds of the frustum
1261 * bottom, top - scalar, bottom and top bounds of the frustum
1262 * near, far - scalar, near and far bounds of the frustum
1263 * dest - Optional, mat4 frustum matrix will be written into
1264 *
1265 * Returns:
1266 * dest if specified, a new mat4 otherwise
1267 */
1268mat4.frustum = function(left, right, bottom, top, near, far, dest) {
1269	if(!dest) { dest = mat4.create(); }
1270	var rl = (right - left);
1271	var tb = (top - bottom);
1272	var fn = (far - near);
1273	dest[0] = (near*2) / rl;
1274	dest[1] = 0;
1275	dest[2] = 0;
1276	dest[3] = 0;
1277	dest[4] = 0;
1278	dest[5] = (near*2) / tb;
1279	dest[6] = 0;
1280	dest[7] = 0;
1281	dest[8] = (right + left) / rl;
1282	dest[9] = (top + bottom) / tb;
1283	dest[10] = -(far + near) / fn;
1284	dest[11] = -1;
1285	dest[12] = 0;
1286	dest[13] = 0;
1287	dest[14] = -(far*near*2) / fn;
1288	dest[15] = 0;
1289	return dest;
1290};
1291
1292/*
1293 * mat4.perspective
1294 * Generates a perspective projection matrix with the given bounds
1295 *
1296 * Params:
1297 * fovy - scalar, vertical field of view
1298 * aspect - scalar, aspect ratio. typically viewport width/height
1299 * near, far - scalar, near and far bounds of the frustum
1300 * dest - Optional, mat4 frustum matrix will be written into
1301 *
1302 * Returns:
1303 * dest if specified, a new mat4 otherwise
1304 */
1305mat4.perspective = function(fovy, aspect, near, far, dest) {
1306	var top = near*Math.tan(fovy*Math.PI / 360.0);
1307	var right = top*aspect;
1308	return mat4.frustum(-right, right, -top, top, near, far, dest);
1309};
1310
1311/*
1312 * mat4.ortho
1313 * Generates a orthogonal projection matrix with the given bounds
1314 *
1315 * Params:
1316 * left, right - scalar, left and right bounds of the frustum
1317 * bottom, top - scalar, bottom and top bounds of the frustum
1318 * near, far - scalar, near and far bounds of the frustum
1319 * dest - Optional, mat4 frustum matrix will be written into
1320 *
1321 * Returns:
1322 * dest if specified, a new mat4 otherwise
1323 */
1324mat4.ortho = function(left, right, bottom, top, near, far, dest) {
1325	if(!dest) { dest = mat4.create(); }
1326	var rl = (right - left);
1327	var tb = (top - bottom);
1328	var fn = (far - near);
1329	dest[0] = 2 / rl;
1330	dest[1] = 0;
1331	dest[2] = 0;
1332	dest[3] = 0;
1333	dest[4] = 0;
1334	dest[5] = 2 / tb;
1335	dest[6] = 0;
1336	dest[7] = 0;
1337	dest[8] = 0;
1338	dest[9] = 0;
1339	dest[10] = -2 / fn;
1340	dest[11] = 0;
1341	dest[12] = -(left + right) / rl;
1342	dest[13] = -(top + bottom) / tb;
1343	dest[14] = -(far + near) / fn;
1344	dest[15] = 1;
1345	return dest;
1346};
1347
1348/*
1349 * mat4.ortho
1350 * Generates a look-at matrix with the given eye position, focal point, and up axis
1351 *
1352 * Params:
1353 * eye - vec3, position of the viewer
1354 * center - vec3, point the viewer is looking at
1355 * up - vec3 pointing "up"
1356 * dest - Optional, mat4 frustum matrix will be written into
1357 *
1358 * Returns:
1359 * dest if specified, a new mat4 otherwise
1360 */
1361mat4.lookAt = function(eye, center, up, dest) {
1362	if(!dest) { dest = mat4.create(); }
1363	
1364	var eyex = eye[0],
1365		eyey = eye[1],
1366		eyez = eye[2],
1367		upx = up[0],
1368		upy = up[1],
1369		upz = up[2],
1370		centerx = center[0],
1371		centery = center[1],
1372		centerz = center[2];
1373
1374	if (eyex == centerx && eyey == centery && eyez == centerz) {
1375		return mat4.identity(dest);
1376	}
1377	
1378	var z0,z1,z2,x0,x1,x2,y0,y1,y2,len;
1379	
1380	//vec3.direction(eye, center, z);
1381	z0 = eyex - center[0];
1382	z1 = eyey - center[1];
1383	z2 = eyez - center[2];
1384	
1385	// normalize (no check needed for 0 because of early return)
1386	len = 1/Math.sqrt(z0*z0 + z1*z1 + z2*z2);
1387	z0 *= len;
1388	z1 *= len;
1389	z2 *= len;
1390	
1391	//vec3.normalize(vec3.cross(up, z, x));
1392	x0 = upy*z2 - upz*z1;
1393	x1 = upz*z0 - upx*z2;
1394	x2 = upx*z1 - upy*z0;
1395	len = Math.sqrt(x0*x0 + x1*x1 + x2*x2);
1396	if (!len) {
1397		x0 = 0;
1398		x1 = 0;
1399		x2 = 0;
1400	} else {
1401		len = 1/len;
1402		x0 *= len;
1403		x1 *= len;
1404		x2 *= len;
1405	};
1406	
1407	//vec3.normalize(vec3.cross(z, x, y));
1408	y0 = z1*x2 - z2*x1;
1409	y1 = z2*x0 - z0*x2;
1410	y2 = z0*x1 - z1*x0;
1411	
1412	len = Math.sqrt(y0*y0 + y1*y1 + y2*y2);
1413	if (!len) {
1414		y0 = 0;
1415		y1 = 0;
1416		y2 = 0;
1417	} else {
1418		len = 1/len;
1419		y0 *= len;
1420		y1 *= len;
1421		y2 *= len;
1422	}
1423	
1424	dest[0] = x0;
1425	dest[1] = y0;
1426	dest[2] = z0;
1427	dest[3] = 0;
1428	dest[4] = x1;
1429	dest[5] = y1;
1430	dest[6] = z1;
1431	dest[7] = 0;
1432	dest[8] = x2;
1433	dest[9] = y2;
1434	dest[10] = z2;
1435	dest[11] = 0;
1436	dest[12] = -(x0*eyex + x1*eyey + x2*eyez);
1437	dest[13] = -(y0*eyex + y1*eyey + y2*eyez);
1438	dest[14] = -(z0*eyex + z1*eyey + z2*eyez);
1439	dest[15] = 1;
1440	
1441	return dest;
1442};
1443
1444/*
1445 * mat4.str
1446 * Returns a string representation of a mat4
1447 *
1448 * Params:
1449 * mat - mat4 to represent as a string
1450 *
1451 * Returns:
1452 * string representation of mat
1453 */
1454mat4.str = function(mat) {
1455	return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + ', ' + mat[3] + 
1456		', '+ mat[4] + ', ' + mat[5] + ', ' + mat[6] + ', ' + mat[7] + 
1457		', '+ mat[8] + ', ' + mat[9] + ', ' + mat[10] + ', ' + mat[11] + 
1458		', '+ mat[12] + ', ' + mat[13] + ', ' + mat[14] + ', ' + mat[15] + ']';
1459};
1460
1461/*
1462 * quat4 - Quaternions 
1463 */
1464quat4 = {};
1465
1466/*
1467 * quat4.create
1468 * Creates a new instance of a quat4 using the default array type
1469 * Any javascript array containing at least 4 numeric elements can serve as a quat4
1470 *
1471 * Params:
1472 * quat - Optional, quat4 containing values to initialize with
1473 *
1474 * Returns:
1475 * New quat4
1476 */
1477quat4.create = function(quat) {
1478	var dest = new glMatrixArrayType(4);
1479	
1480	if(quat) {
1481		dest[0] = quat[0];
1482		dest[1] = quat[1];
1483		dest[2] = quat[2];
1484		dest[3] = quat[3];
1485	}
1486	
1487	return dest;
1488};
1489
1490/*
1491 * quat4.set
1492 * Copies the values of one quat4 to another
1493 *
1494 * Params:
1495 * quat - quat4 containing values to copy
1496 * dest - quat4 receiving copied values
1497 *
1498 * Returns:
1499 * dest
1500 */
1501quat4.set = function(quat, dest) {
1502	dest[0] = quat[0];
1503	dest[1] = quat[1];
1504	dest[2] = quat[2];
1505	dest[3] = quat[3];
1506	
1507	return dest;
1508};
1509
1510/*
1511 * quat4.calculateW
1512 * Calculates the W component of a quat4 from the X, Y, and Z components.
1513 * Assumes that quaternion is 1 unit in length. 
1514 * Any existing W component will be ignored. 
1515 *
1516 * Params:
1517 * quat - quat4 to calculate W component of
1518 * dest - Optional, quat4 receiving calculated values. If not specified result is written to quat
1519 *
1520 * Returns:
1521 * dest if specified, quat otherwise
1522 */
1523quat4.calculateW = function(quat, dest) {
1524	var x = quat[0], y = quat[1], z = quat[2];
1525
1526	if(!dest || quat == dest) {
1527		quat[3] = -Math.sqrt(Math.abs(1.0 - x*x - y*y - z*z));
1528		return quat;
1529	}
1530	dest[0] = x;
1531	dest[1] = y;
1532	dest[2] = z;
1533	dest[3] = -Math.sqrt(Math.abs(1.0 - x*x - y*y - z*z));
1534	return dest;
1535}
1536
1537/*
1538 * quat4.inverse
1539 * Calculates the inverse of a quat4
1540 *
1541 * Params:
1542 * quat - quat4 to calculate inverse of
1543 * dest - Optional, quat4 receiving inverse values. If not specified result is written to quat
1544 *
1545 * Returns:
1546 * dest if specified, quat otherwise
1547 */
1548quat4.inverse = function(quat, dest) {
1549	if(!dest || quat == dest) {
1550		quat[0] *= -1;
1551		quat[1] *= -1;
1552		quat[2] *= -1;
1553		return quat;
1554	}
1555	dest[0] = -quat[0];
1556	dest[1] = -quat[1];
1557	dest[2] = -quat[2];
1558	dest[3] = quat[3];
1559	return dest;
1560}
1561
1562/*
1563 * quat4.length
1564 * Calculates the length of a quat4
1565 *
1566 * Params:
1567 * quat - quat4 to calculate length of
1568 *
1569 * Returns:
1570 * Length of quat
1571 */
1572quat4.length = function(quat) {
1573	var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
1574	return Math.sqrt(x*x + y*y + z*z + w*w);
1575}
1576
1577/*
1578 * quat4.normalize
1579 * Generates a unit quaternion of the same direction as the provided quat4
1580 * If quaternion length is 0, returns [0, 0, 0, 0]
1581 *
1582 * Params:
1583 * quat - quat4 to normalize
1584 * dest - Optional, quat4 receiving operation result. If not specified result is written to quat
1585 *
1586 * Returns:
1587 * dest if specified, quat otherwise
1588 */
1589quat4.normalize = function(quat, dest) {
1590	if(!dest) { dest = quat; }
1591	
1592	var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
1593	var len = Math.sqrt(x*x + y*y + z*z + w*w);
1594	if(len == 0) {
1595		dest[0] = 0;
1596		dest[1] = 0;
1597		dest[2] = 0;
1598		dest[3] = 0;
1599		return dest;
1600	}
1601	len = 1/len;
1602	dest[0] = x * len;
1603	dest[1] = y * len;
1604	dest[2] = z * len;
1605	dest[3] = w * len;
1606	
1607	return dest;
1608}
1609
1610/*
1611 * quat4.multiply
1612 * Performs a quaternion multiplication
1613 *
1614 * Params:
1615 * quat - quat4, first operand
1616 * quat2 - quat4, second operand
1617 * dest - Optional, quat4 receiving operation result. If not specified result is written to quat
1618 *
1619 * Returns:
1620 * dest if specified, quat otherwise
1621 */
1622quat4.multiply = function(quat, quat2, dest) {
1623	if(!dest) { dest = quat; }
1624	
1625	var qax = quat[0], qay = quat[1], qaz = quat[2], qaw = quat[3];
1626	var qbx = quat2[0], qby = quat2[1], qbz = quat2[2], qbw = quat2[3];
1627	
1628	dest[0] = qax*qbw + qaw*qbx + qay*qbz - qaz*qby;
1629	dest[1] = qay*qbw + qaw*qby + qaz*qbx - qax*qbz;
1630	dest[2] = qaz*qbw + qaw*qbz + qax*qby - qay*qbx;
1631	dest[3] = qaw*qbw - qax*qbx - qay*qby - qaz*qbz;
1632	
1633	return dest;
1634}
1635
1636/*
1637 * quat4.multiplyVec3
1638 * Transforms a vec3 with the given quaternion
1639 *
1640 * Params:
1641 * quat - quat4 to transform the vector with
1642 * vec - vec3 to transform
1643 * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
1644 *
1645 * Returns:
1646 * dest if specified, vec otherwise
1647 */
1648quat4.multiplyVec3 = function(quat, vec, dest) {
1649	if(!dest) { dest = vec; }
1650	
1651	var x = vec[0], y = vec[1], z = vec[2];
1652	var qx = quat[0], qy = quat[1], qz = quat[2], qw = quat[3];
1653
1654	// calculate quat * vec
1655	var ix = qw*x + qy*z - qz*y;
1656	var iy = qw*y + qz*x - qx*z;
1657	var iz = qw*z + qx*y - qy*x;
1658	var iw = -qx*x - qy*y - qz*z;
1659	
1660	// calculate result * inverse quat
1661	dest[0] = ix*qw + iw*-qx + iy*-qz - iz*-qy;
1662	dest[1] = iy*qw + iw*-qy + iz*-qx - ix*-qz;
1663	dest[2] = iz*qw + iw*-qz + ix*-qy - iy*-qx;
1664	
1665	return dest;
1666}
1667
1668/*
1669 * quat4.toMat3
1670 * Calculates a 3x3 matrix from the given quat4
1671 *
1672 * Params:
1673 * quat - quat4 to create matrix from
1674 * dest - Optional, mat3 receiving operation result
1675 *
1676 * Returns:
1677 * dest if specified, a new mat3 otherwise
1678 */
1679quat4.toMat3 = function(quat, dest) {
1680	if(!dest) { dest = mat3.create(); }
1681	
1682	var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
1683
1684	var x2 = x + x;
1685	var y2 = y + y;
1686	var z2 = z + z;
1687
1688	var xx = x*x2;
1689	var xy = x*y2;
1690	var xz = x*z2;
1691
1692	var yy = y*y2;
1693	var yz = y*z2;
1694	var zz = z*z2;
1695
1696	var wx = w*x2;
1697	var wy = w*y2;
1698	var wz = w*z2;
1699
1700	dest[0] = 1 - (yy + zz);
1701	dest[1] = xy - wz;
1702	dest[2] = xz + wy;
1703
1704	dest[3] = xy + wz;
1705	dest[4] = 1 - (xx + zz);
1706	dest[5] = yz - wx;
1707
1708	dest[6] = xz - wy;
1709	dest[7] = yz + wx;
1710	dest[8] = 1 - (xx + yy);
1711	
1712	return dest;
1713}
1714
1715/*
1716 * quat4.toMat4
1717 * Calculates a 4x4 matrix from the given quat4
1718 *
1719 * Params:
1720 * quat - quat4 to create matrix from
1721 * dest - Optional, mat4 receiving operation result
1722 *
1723 * Returns:
1724 * dest if specified, a new mat4 otherwise
1725 */
1726quat4.toMat4 = function(quat, dest) {
1727	if(!dest) { dest = mat4.create(); }
1728	
1729	var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
1730
1731	var x2 = x + x;
1732	var y2 = y + y;
1733	var z2 = z + z;
1734
1735	var xx = x*x2;
1736	var xy = x*y2;
1737	var xz = x*z2;
1738
1739	var yy = y*y2;
1740	var yz = y*z2;
1741	var zz = z*z2;
1742
1743	var wx = w*x2;
1744	var wy = w*y2;
1745	var wz = w*z2;
1746
1747	dest[0] = 1 - (yy + zz);
1748	dest[1] = xy - wz;
1749	dest[2] = xz + wy;
1750	dest[3] = 0;
1751
1752	dest[4] = xy + wz;
1753	dest[5] = 1 - (xx + zz);
1754	dest[6] = yz - wx;
1755	dest[7] = 0;
1756
1757	dest[8] = xz - wy;
1758	dest[9] = yz + wx;
1759	dest[10] = 1 - (xx + yy);
1760	dest[11] = 0;
1761
1762	dest[12] = 0;
1763	dest[13] = 0;
1764	dest[14] = 0;
1765	dest[15] = 1;
1766	
1767	return dest;
1768}
1769
1770/*
1771 * quat4.slerp
1772 * Performs a spherical linear interpolation between two quat4
1773 *
1774 * Params:
1775 * quat - quat4, first quaternion
1776 * quat2 - quat4, second quaternion
1777 * slerp - interpolation amount between the two inputs
1778 * dest - Optional, quat4 receiving operation result. If not specified result is written to quat
1779 *
1780 * Returns:
1781 * dest if specified, quat otherwise
1782 */
1783quat4.slerp = function(quat, quat2, slerp, dest) {
1784    if(!dest) { dest = quat; }
1785    
1786	var cosHalfTheta =  quat[0]*quat2[0] + quat[1]*quat2[1] + quat[2]*quat2[2] + quat[3]*quat2[3];
1787	
1788	if (Math.abs(cosHalfTheta) >= 1.0){
1789	    if(dest != quat) {
1790		    dest[0] = quat[0];
1791		    dest[1] = quat[1];
1792		    dest[2] = quat[2];
1793		    dest[3] = quat[3];
1794		}
1795		return dest;
1796	}
1797	
1798	var halfTheta = Math.acos(cosHalfTheta);
1799	var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta*cosHalfTheta);
1800
1801	if (Math.abs(sinHalfTheta) < 0.001){
1802		dest[0] = (quat[0]*0.5 + quat2[0]*0.5);
1803		dest[1] = (quat[1]*0.5 + quat2[1]*0.5);
1804		dest[2] = (quat[2]*0.5 + quat2[2]*0.5);
1805		dest[3] = (quat[3]*0.5 + quat2[3]*0.5);
1806		return dest;
1807	}
1808	
1809	var ratioA = Math.sin((1 - slerp)*halfTheta) / sinHalfTheta;
1810	var ratioB = Math.sin(slerp*halfTheta) / sinHalfTheta; 
1811	
1812	dest[0] = (quat[0]*ratioA + quat2[0]*ratioB);
1813	dest[1] = (quat[1]*ratioA + quat2[1]*ratioB);
1814	dest[2] = (quat[2]*ratioA + quat2[2]*ratioB);
1815	dest[3] = (quat[3]*ratioA + quat2[3]*ratioB);
1816	
1817	return dest;
1818}
1819
1820
1821/*
1822 * quat4.str
1823 * Returns a string representation of a quaternion
1824 *
1825 * Params:
1826 * quat - quat4 to represent as a string
1827 *
1828 * Returns:
1829 * string representation of quat
1830 */
1831quat4.str = function(quat) {
1832	return '[' + quat[0] + ', ' + quat[1] + ', ' + quat[2] + ', ' + quat[3] + ']'; 
1833}
1834

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.