gallery3d: Add new widget
[platform/framework/web/web-ui-fw.git] / libs / js / gl-matrix.js
1 /**
2  * @fileoverview gl-matrix - High performance matrix and vector operations for WebGL
3  * @author Brandon Jones
4  * @author Colin MacKenzie IV
5  * @version 1.3.7
6  */
7
8 /*
9  * Copyright (c) 2012 Brandon Jones, Colin MacKenzie IV
10  *
11  * This software is provided 'as-is', without any express or implied
12  * warranty. In no event will the authors be held liable for any damages
13  * arising from the use of this software.
14  *
15  * Permission is granted to anyone to use this software for any purpose,
16  * including commercial applications, and to alter it and redistribute it
17  * freely, subject to the following restrictions:
18  *
19  *    1. The origin of this software must not be misrepresented; you must not
20  *    claim that you wrote the original software. If you use this software
21  *    in a product, an acknowledgment in the product documentation would be
22  *    appreciated but is not required.
23  *
24  *    2. Altered source versions must be plainly marked as such, and must not
25  *    be misrepresented as being the original software.
26  *
27  *    3. This notice may not be removed or altered from any source
28  *    distribution.
29  */
30
31 // Updated to use a modification of the "returnExportsGlobal" pattern from https://github.com/umdjs/umd
32
33 (function (root, factory) {
34     if (typeof exports === 'object') {
35         // Node. Does not work with strict CommonJS, but
36         // only CommonJS-like enviroments that support module.exports,
37         // like Node.
38         module.exports = factory(global);
39     } else if (typeof define === 'function' && define.amd) {
40         // AMD. Register as an anonymous module.
41         define([], function () {
42             return factory(root);
43         });
44     } else {
45         // Browser globals
46         factory(root);
47     }
48 }(this, function (root) {
49     "use strict";
50
51     // Tweak to your liking
52     var FLOAT_EPSILON = 0.000001;
53
54     var glMath = {};
55     (function() {
56         if (typeof(Float32Array) != 'undefined') {
57             var y = new Float32Array(1);
58             var i = new Int32Array(y.buffer);
59
60             /**
61              * Fast way to calculate the inverse square root,
62              * see http://jsperf.com/inverse-square-root/5
63              *
64              * If typed arrays are not available, a slower
65              * implementation will be used.
66              *
67              * @param {Number} number the number
68              * @returns {Number} Inverse square root
69              */
70             glMath.invsqrt = function(number) {
71               var x2 = number * 0.5;
72               y[0] = number;
73               var threehalfs = 1.5;
74
75               i[0] = 0x5f3759df - (i[0] >> 1);
76
77               var number2 = y[0];
78
79               return number2 * (threehalfs - (x2 * number2 * number2));
80             };
81         } else {
82             glMath.invsqrt = function(number) { return 1.0 / Math.sqrt(number); };
83         }
84     })();
85
86     /**
87      * @class System-specific optimal array type
88      * @name MatrixArray
89      */
90     var MatrixArray = null;
91     
92     // explicitly sets and returns the type of array to use within glMatrix
93     function setMatrixArrayType(type) {
94         MatrixArray = type;
95         return MatrixArray;
96     }
97
98     // auto-detects and returns the best type of array to use within glMatrix, falling
99     // back to Array if typed arrays are unsupported
100     function determineMatrixArrayType() {
101         MatrixArray = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
102         return MatrixArray;
103     }
104     
105     determineMatrixArrayType();
106
107     /**
108      * @class 3 Dimensional Vector
109      * @name vec3
110      */
111     var vec3 = {};
112      
113     /**
114      * Creates a new instance of a vec3 using the default array type
115      * Any javascript array-like objects containing at least 3 numeric elements can serve as a vec3
116      *
117      * @param {vec3} [vec] vec3 containing values to initialize with
118      *
119      * @returns {vec3} New vec3
120      */
121     vec3.create = function (vec) {
122         var dest = new MatrixArray(3);
123
124         if (vec) {
125             dest[0] = vec[0];
126             dest[1] = vec[1];
127             dest[2] = vec[2];
128         } else {
129             dest[0] = dest[1] = dest[2] = 0;
130         }
131
132         return dest;
133     };
134
135     /**
136      * Creates a new instance of a vec3, initializing it with the given arguments
137      *
138      * @param {number} x X value
139      * @param {number} y Y value
140      * @param {number} z Z value
141
142      * @returns {vec3} New vec3
143      */
144     vec3.createFrom = function (x, y, z) {
145         var dest = new MatrixArray(3);
146
147         dest[0] = x;
148         dest[1] = y;
149         dest[2] = z;
150
151         return dest;
152     };
153
154     /**
155      * Copies the values of one vec3 to another
156      *
157      * @param {vec3} vec vec3 containing values to copy
158      * @param {vec3} dest vec3 receiving copied values
159      *
160      * @returns {vec3} dest
161      */
162     vec3.set = function (vec, dest) {
163         dest[0] = vec[0];
164         dest[1] = vec[1];
165         dest[2] = vec[2];
166
167         return dest;
168     };
169
170     /**
171      * Compares two vectors for equality within a certain margin of error
172      *
173      * @param {vec3} a First vector
174      * @param {vec3} b Second vector
175      *
176      * @returns {Boolean} True if a is equivalent to b
177      */
178     vec3.equal = function (a, b) {
179         return a === b || (
180             Math.abs(a[0] - b[0]) < FLOAT_EPSILON &&
181             Math.abs(a[1] - b[1]) < FLOAT_EPSILON &&
182             Math.abs(a[2] - b[2]) < FLOAT_EPSILON
183         );
184     };
185
186     /**
187      * Performs a vector addition
188      *
189      * @param {vec3} vec First operand
190      * @param {vec3} vec2 Second operand
191      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
192      *
193      * @returns {vec3} dest if specified, vec otherwise
194      */
195     vec3.add = function (vec, vec2, dest) {
196         if (!dest || vec === dest) {
197             vec[0] += vec2[0];
198             vec[1] += vec2[1];
199             vec[2] += vec2[2];
200             return vec;
201         }
202
203         dest[0] = vec[0] + vec2[0];
204         dest[1] = vec[1] + vec2[1];
205         dest[2] = vec[2] + vec2[2];
206         return dest;
207     };
208
209     /**
210      * Performs a vector subtraction
211      *
212      * @param {vec3} vec First operand
213      * @param {vec3} vec2 Second operand
214      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
215      *
216      * @returns {vec3} dest if specified, vec otherwise
217      */
218     vec3.subtract = function (vec, vec2, dest) {
219         if (!dest || vec === dest) {
220             vec[0] -= vec2[0];
221             vec[1] -= vec2[1];
222             vec[2] -= vec2[2];
223             return vec;
224         }
225
226         dest[0] = vec[0] - vec2[0];
227         dest[1] = vec[1] - vec2[1];
228         dest[2] = vec[2] - vec2[2];
229         return dest;
230     };
231
232     /**
233      * Performs a vector multiplication
234      *
235      * @param {vec3} vec First operand
236      * @param {vec3} vec2 Second operand
237      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
238      *
239      * @returns {vec3} dest if specified, vec otherwise
240      */
241     vec3.multiply = function (vec, vec2, dest) {
242         if (!dest || vec === dest) {
243             vec[0] *= vec2[0];
244             vec[1] *= vec2[1];
245             vec[2] *= vec2[2];
246             return vec;
247         }
248
249         dest[0] = vec[0] * vec2[0];
250         dest[1] = vec[1] * vec2[1];
251         dest[2] = vec[2] * vec2[2];
252         return dest;
253     };
254
255     /**
256      * Negates the components of a vec3
257      *
258      * @param {vec3} vec vec3 to negate
259      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
260      *
261      * @returns {vec3} dest if specified, vec otherwise
262      */
263     vec3.negate = function (vec, dest) {
264         if (!dest) { dest = vec; }
265
266         dest[0] = -vec[0];
267         dest[1] = -vec[1];
268         dest[2] = -vec[2];
269         return dest;
270     };
271
272     /**
273      * Multiplies the components of a vec3 by a scalar value
274      *
275      * @param {vec3} vec vec3 to scale
276      * @param {number} val Value to scale by
277      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
278      *
279      * @returns {vec3} dest if specified, vec otherwise
280      */
281     vec3.scale = function (vec, val, dest) {
282         if (!dest || vec === dest) {
283             vec[0] *= val;
284             vec[1] *= val;
285             vec[2] *= val;
286             return vec;
287         }
288
289         dest[0] = vec[0] * val;
290         dest[1] = vec[1] * val;
291         dest[2] = vec[2] * val;
292         return dest;
293     };
294
295     /**
296      * Generates a unit vector of the same direction as the provided vec3
297      * If vector length is 0, returns [0, 0, 0]
298      *
299      * @param {vec3} vec vec3 to normalize
300      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
301      *
302      * @returns {vec3} dest if specified, vec otherwise
303      */
304     vec3.normalize = function (vec, dest) {
305         if (!dest) { dest = vec; }
306
307         var x = vec[0], y = vec[1], z = vec[2],
308             len = Math.sqrt(x * x + y * y + z * z);
309
310         if (!len) {
311             dest[0] = 0;
312             dest[1] = 0;
313             dest[2] = 0;
314             return dest;
315         } else if (len === 1) {
316             dest[0] = x;
317             dest[1] = y;
318             dest[2] = z;
319             return dest;
320         }
321
322         len = 1 / len;
323         dest[0] = x * len;
324         dest[1] = y * len;
325         dest[2] = z * len;
326         return dest;
327     };
328
329     /**
330      * Generates the cross product of two vec3s
331      *
332      * @param {vec3} vec First operand
333      * @param {vec3} vec2 Second operand
334      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
335      *
336      * @returns {vec3} dest if specified, vec otherwise
337      */
338     vec3.cross = function (vec, vec2, dest) {
339         if (!dest) { dest = vec; }
340
341         var x = vec[0], y = vec[1], z = vec[2],
342             x2 = vec2[0], y2 = vec2[1], z2 = vec2[2];
343
344         dest[0] = y * z2 - z * y2;
345         dest[1] = z * x2 - x * z2;
346         dest[2] = x * y2 - y * x2;
347         return dest;
348     };
349
350     /**
351      * Caclulates the length of a vec3
352      *
353      * @param {vec3} vec vec3 to calculate length of
354      *
355      * @returns {number} Length of vec
356      */
357     vec3.length = function (vec) {
358         var x = vec[0], y = vec[1], z = vec[2];
359         return Math.sqrt(x * x + y * y + z * z);
360     };
361
362     /**
363      * Caclulates the squared length of a vec3
364      *
365      * @param {vec3} vec vec3 to calculate squared length of
366      *
367      * @returns {number} Squared Length of vec
368      */
369     vec3.squaredLength = function (vec) {
370         var x = vec[0], y = vec[1], z = vec[2];
371         return x * x + y * y + z * z;
372     };
373
374     /**
375      * Caclulates the dot product of two vec3s
376      *
377      * @param {vec3} vec First operand
378      * @param {vec3} vec2 Second operand
379      *
380      * @returns {number} Dot product of vec and vec2
381      */
382     vec3.dot = function (vec, vec2) {
383         return vec[0] * vec2[0] + vec[1] * vec2[1] + vec[2] * vec2[2];
384     };
385
386     /**
387      * Generates a unit vector pointing from one vector to another
388      *
389      * @param {vec3} vec Origin vec3
390      * @param {vec3} vec2 vec3 to point to
391      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
392      *
393      * @returns {vec3} dest if specified, vec otherwise
394      */
395     vec3.direction = function (vec, vec2, dest) {
396         if (!dest) { dest = vec; }
397
398         var x = vec[0] - vec2[0],
399             y = vec[1] - vec2[1],
400             z = vec[2] - vec2[2],
401             len = Math.sqrt(x * x + y * y + z * z);
402
403         if (!len) {
404             dest[0] = 0;
405             dest[1] = 0;
406             dest[2] = 0;
407             return dest;
408         }
409
410         len = 1 / len;
411         dest[0] = x * len;
412         dest[1] = y * len;
413         dest[2] = z * len;
414         return dest;
415     };
416
417     /**
418      * Performs a linear interpolation between two vec3
419      *
420      * @param {vec3} vec First vector
421      * @param {vec3} vec2 Second vector
422      * @param {number} lerp Interpolation amount between the two inputs
423      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
424      *
425      * @returns {vec3} dest if specified, vec otherwise
426      */
427     vec3.lerp = function (vec, vec2, lerp, dest) {
428         if (!dest) { dest = vec; }
429
430         dest[0] = vec[0] + lerp * (vec2[0] - vec[0]);
431         dest[1] = vec[1] + lerp * (vec2[1] - vec[1]);
432         dest[2] = vec[2] + lerp * (vec2[2] - vec[2]);
433
434         return dest;
435     };
436
437     /**
438      * Calculates the euclidian distance between two vec3
439      *
440      * Params:
441      * @param {vec3} vec First vector
442      * @param {vec3} vec2 Second vector
443      *
444      * @returns {number} Distance between vec and vec2
445      */
446     vec3.dist = function (vec, vec2) {
447         var x = vec2[0] - vec[0],
448             y = vec2[1] - vec[1],
449             z = vec2[2] - vec[2];
450             
451         return Math.sqrt(x*x + y*y + z*z);
452     };
453
454     // Pre-allocated to prevent unecessary garbage collection
455     var unprojectMat = null;
456     var unprojectVec = new MatrixArray(4);
457     /**
458      * Projects the specified vec3 from screen space into object space
459      * Based on the <a href="http://webcvs.freedesktop.org/mesa/Mesa/src/glu/mesa/project.c?revision=1.4&view=markup">Mesa gluUnProject implementation</a>
460      *
461      * @param {vec3} vec Screen-space vector to project
462      * @param {mat4} view View matrix
463      * @param {mat4} proj Projection matrix
464      * @param {vec4} viewport Viewport as given to gl.viewport [x, y, width, height]
465      * @param {vec3} [dest] vec3 receiving unprojected result. If not specified result is written to vec
466      *
467      * @returns {vec3} dest if specified, vec otherwise
468      */
469     vec3.unproject = function (vec, view, proj, viewport, dest) {
470         if (!dest) { dest = vec; }
471
472         if(!unprojectMat) {
473             unprojectMat = mat4.create();
474         }
475
476         var m = unprojectMat;
477         var v = unprojectVec;
478         
479         v[0] = (vec[0] - viewport[0]) * 2.0 / viewport[2] - 1.0;
480         v[1] = (vec[1] - viewport[1]) * 2.0 / viewport[3] - 1.0;
481         v[2] = 2.0 * vec[2] - 1.0;
482         v[3] = 1.0;
483         
484         mat4.multiply(proj, view, m);
485         if(!mat4.inverse(m)) { return null; }
486         
487         mat4.multiplyVec4(m, v);
488         if(v[3] === 0.0) { return null; }
489
490         dest[0] = v[0] / v[3];
491         dest[1] = v[1] / v[3];
492         dest[2] = v[2] / v[3];
493         
494         return dest;
495     };
496
497     var xUnitVec3 = vec3.createFrom(1,0,0);
498     var yUnitVec3 = vec3.createFrom(0,1,0);
499     var zUnitVec3 = vec3.createFrom(0,0,1);
500
501     var tmpvec3 = vec3.create();
502     /**
503      * Generates a quaternion of rotation between two given normalized vectors
504      *
505      * @param {vec3} a Normalized source vector
506      * @param {vec3} b Normalized target vector
507      * @param {quat4} [dest] quat4 receiving operation result.
508      *
509      * @returns {quat4} dest if specified, a new quat4 otherwise
510      */
511     vec3.rotationTo = function (a, b, dest) {
512         if (!dest) { dest = quat4.create(); }
513         
514         var d = vec3.dot(a, b);
515         var axis = tmpvec3;
516         if (d >= 1.0) {
517             quat4.set(identityQuat4, dest);
518         } else if (d < (0.000001 - 1.0)) {
519             vec3.cross(xUnitVec3, a, axis);
520             if (vec3.length(axis) < 0.000001)
521                 vec3.cross(yUnitVec3, a, axis);
522             if (vec3.length(axis) < 0.000001)
523                 vec3.cross(zUnitVec3, a, axis);
524             vec3.normalize(axis);
525             quat4.fromAngleAxis(Math.PI, axis, dest);
526         } else {
527             var s = Math.sqrt((1.0 + d) * 2.0);
528             var sInv = 1.0 / s;
529             vec3.cross(a, b, axis);
530             dest[0] = axis[0] * sInv;
531             dest[1] = axis[1] * sInv;
532             dest[2] = axis[2] * sInv;
533             dest[3] = s * 0.5;
534             quat4.normalize(dest);
535         }
536         if (dest[3] > 1.0) dest[3] = 1.0;
537         else if (dest[3] < -1.0) dest[3] = -1.0;
538         return dest;
539     };
540
541     /**
542      * Returns a string representation of a vector
543      *
544      * @param {vec3} vec Vector to represent as a string
545      *
546      * @returns {string} String representation of vec
547      */
548     vec3.str = function (vec) {
549         return '[' + vec[0] + ', ' + vec[1] + ', ' + vec[2] + ']';
550     };
551
552     /**
553      * @class 3x3 Matrix
554      * @name mat3
555      */
556     var mat3 = {};
557
558     /**
559      * Creates a new instance of a mat3 using the default array type
560      * Any javascript array-like object containing at least 9 numeric elements can serve as a mat3
561      *
562      * @param {mat3} [mat] mat3 containing values to initialize with
563      *
564      * @returns {mat3} New mat3
565      */
566     mat3.create = function (mat) {
567         var dest = new MatrixArray(9);
568
569         if (mat) {
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         } else {
580             dest[0] = dest[1] =
581             dest[2] = dest[3] =
582             dest[4] = dest[5] =
583             dest[6] = dest[7] =
584             dest[8] = 0;
585         }
586
587         return dest;
588     };
589
590     /**
591      * Creates a new instance of a mat3, initializing it with the given arguments
592      *
593      * @param {number} m00
594      * @param {number} m01
595      * @param {number} m02
596      * @param {number} m10
597      * @param {number} m11
598      * @param {number} m12
599      * @param {number} m20
600      * @param {number} m21
601      * @param {number} m22
602
603      * @returns {mat3} New mat3
604      */
605     mat3.createFrom = function (m00, m01, m02, m10, m11, m12, m20, m21, m22) {
606         var dest = new MatrixArray(9);
607
608         dest[0] = m00;
609         dest[1] = m01;
610         dest[2] = m02;
611         dest[3] = m10;
612         dest[4] = m11;
613         dest[5] = m12;
614         dest[6] = m20;
615         dest[7] = m21;
616         dest[8] = m22;
617
618         return dest;
619     };
620
621     /**
622      * Calculates the determinant of a mat3
623      *
624      * @param {mat3} mat mat3 to calculate determinant of
625      *
626      * @returns {Number} determinant of mat
627      */
628     mat3.determinant = function (mat) {
629         var a00 = mat[0], a01 = mat[1], a02 = mat[2],
630             a10 = mat[3], a11 = mat[4], a12 = mat[5],
631             a20 = mat[6], a21 = mat[7], a22 = mat[8];
632
633         return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
634     };
635
636     /**
637      * Calculates the inverse matrix of a mat3
638      *
639      * @param {mat3} mat mat3 to calculate inverse of
640      * @param {mat3} [dest] mat3 receiving inverse matrix. If not specified result is written to mat
641      *
642      * @param {mat3} dest is specified, mat otherwise, null if matrix cannot be inverted
643      */
644     mat3.inverse = function (mat, dest) {
645         var a00 = mat[0], a01 = mat[1], a02 = mat[2],
646             a10 = mat[3], a11 = mat[4], a12 = mat[5],
647             a20 = mat[6], a21 = mat[7], a22 = mat[8],
648
649             b01 = a22 * a11 - a12 * a21,
650             b11 = -a22 * a10 + a12 * a20,
651             b21 = a21 * a10 - a11 * a20,
652
653             d = a00 * b01 + a01 * b11 + a02 * b21,
654             id;
655
656         if (!d) { return null; }
657         id = 1 / d;
658
659         if (!dest) { dest = mat3.create(); }
660
661         dest[0] = b01 * id;
662         dest[1] = (-a22 * a01 + a02 * a21) * id;
663         dest[2] = (a12 * a01 - a02 * a11) * id;
664         dest[3] = b11 * id;
665         dest[4] = (a22 * a00 - a02 * a20) * id;
666         dest[5] = (-a12 * a00 + a02 * a10) * id;
667         dest[6] = b21 * id;
668         dest[7] = (-a21 * a00 + a01 * a20) * id;
669         dest[8] = (a11 * a00 - a01 * a10) * id;
670         return dest;
671     };
672     
673     /**
674      * Performs a matrix multiplication
675      *
676      * @param {mat3} mat First operand
677      * @param {mat3} mat2 Second operand
678      * @param {mat3} [dest] mat3 receiving operation result. If not specified result is written to mat
679      *
680      * @returns {mat3} dest if specified, mat otherwise
681      */
682     mat3.multiply = function (mat, mat2, dest) {
683         if (!dest) { dest = mat; }
684         
685
686         // Cache the matrix values (makes for huge speed increases!)
687         var a00 = mat[0], a01 = mat[1], a02 = mat[2],
688             a10 = mat[3], a11 = mat[4], a12 = mat[5],
689             a20 = mat[6], a21 = mat[7], a22 = mat[8],
690
691             b00 = mat2[0], b01 = mat2[1], b02 = mat2[2],
692             b10 = mat2[3], b11 = mat2[4], b12 = mat2[5],
693             b20 = mat2[6], b21 = mat2[7], b22 = mat2[8];
694
695         dest[0] = b00 * a00 + b01 * a10 + b02 * a20;
696         dest[1] = b00 * a01 + b01 * a11 + b02 * a21;
697         dest[2] = b00 * a02 + b01 * a12 + b02 * a22;
698
699         dest[3] = b10 * a00 + b11 * a10 + b12 * a20;
700         dest[4] = b10 * a01 + b11 * a11 + b12 * a21;
701         dest[5] = b10 * a02 + b11 * a12 + b12 * a22;
702
703         dest[6] = b20 * a00 + b21 * a10 + b22 * a20;
704         dest[7] = b20 * a01 + b21 * a11 + b22 * a21;
705         dest[8] = b20 * a02 + b21 * a12 + b22 * a22;
706
707         return dest;
708     };
709
710     /**
711      * Transforms the vec2 according to the given mat3.
712      *
713      * @param {mat3} matrix mat3 to multiply against
714      * @param {vec2} vec    the vector to multiply
715      * @param {vec2} [dest] an optional receiving vector. If not given, vec is used.
716      *
717      * @returns {vec2} The multiplication result
718      **/
719     mat3.multiplyVec2 = function(matrix, vec, dest) {
720       if (!dest) dest = vec;
721       var x = vec[0], y = vec[1];
722       dest[0] = x * matrix[0] + y * matrix[3] + matrix[6];
723       dest[1] = x * matrix[1] + y * matrix[4] + matrix[7];
724       return dest;
725     };
726
727     /**
728      * Transforms the vec3 according to the given mat3
729      *
730      * @param {mat3} matrix mat3 to multiply against
731      * @param {vec3} vec    the vector to multiply
732      * @param {vec3} [dest] an optional receiving vector. If not given, vec is used.
733      *
734      * @returns {vec3} The multiplication result
735      **/
736     mat3.multiplyVec3 = function(matrix, vec, dest) {
737       if (!dest) dest = vec;
738       var x = vec[0], y = vec[1], z = vec[2];
739       dest[0] = x * matrix[0] + y * matrix[3] + z * matrix[6];
740       dest[1] = x * matrix[1] + y * matrix[4] + z * matrix[7];
741       dest[2] = x * matrix[2] + y * matrix[5] + z * matrix[8];
742       
743       return dest;
744     };
745
746     /**
747      * Copies the values of one mat3 to another
748      *
749      * @param {mat3} mat mat3 containing values to copy
750      * @param {mat3} dest mat3 receiving copied values
751      *
752      * @returns {mat3} dest
753      */
754     mat3.set = function (mat, dest) {
755         dest[0] = mat[0];
756         dest[1] = mat[1];
757         dest[2] = mat[2];
758         dest[3] = mat[3];
759         dest[4] = mat[4];
760         dest[5] = mat[5];
761         dest[6] = mat[6];
762         dest[7] = mat[7];
763         dest[8] = mat[8];
764         return dest;
765     };
766
767     /**
768      * Compares two matrices for equality within a certain margin of error
769      *
770      * @param {mat3} a First matrix
771      * @param {mat3} b Second matrix
772      *
773      * @returns {Boolean} True if a is equivalent to b
774      */
775     mat3.equal = function (a, b) {
776         return a === b || (
777             Math.abs(a[0] - b[0]) < FLOAT_EPSILON &&
778             Math.abs(a[1] - b[1]) < FLOAT_EPSILON &&
779             Math.abs(a[2] - b[2]) < FLOAT_EPSILON &&
780             Math.abs(a[3] - b[3]) < FLOAT_EPSILON &&
781             Math.abs(a[4] - b[4]) < FLOAT_EPSILON &&
782             Math.abs(a[5] - b[5]) < FLOAT_EPSILON &&
783             Math.abs(a[6] - b[6]) < FLOAT_EPSILON &&
784             Math.abs(a[7] - b[7]) < FLOAT_EPSILON &&
785             Math.abs(a[8] - b[8]) < FLOAT_EPSILON
786         );
787     };
788
789     /**
790      * Sets a mat3 to an identity matrix
791      *
792      * @param {mat3} dest mat3 to set
793      *
794      * @returns dest if specified, otherwise a new mat3
795      */
796     mat3.identity = function (dest) {
797         if (!dest) { dest = mat3.create(); }
798         dest[0] = 1;
799         dest[1] = 0;
800         dest[2] = 0;
801         dest[3] = 0;
802         dest[4] = 1;
803         dest[5] = 0;
804         dest[6] = 0;
805         dest[7] = 0;
806         dest[8] = 1;
807         return dest;
808     };
809
810     /**
811      * Transposes a mat3 (flips the values over the diagonal)
812      *
813      * Params:
814      * @param {mat3} mat mat3 to transpose
815      * @param {mat3} [dest] mat3 receiving transposed values. If not specified result is written to mat
816      *
817      * @returns {mat3} dest is specified, mat otherwise
818      */
819     mat3.transpose = function (mat, dest) {
820         // If we are transposing ourselves we can skip a few steps but have to cache some values
821         if (!dest || mat === dest) {
822             var a01 = mat[1], a02 = mat[2],
823                 a12 = mat[5];
824
825             mat[1] = mat[3];
826             mat[2] = mat[6];
827             mat[3] = a01;
828             mat[5] = mat[7];
829             mat[6] = a02;
830             mat[7] = a12;
831             return mat;
832         }
833
834         dest[0] = mat[0];
835         dest[1] = mat[3];
836         dest[2] = mat[6];
837         dest[3] = mat[1];
838         dest[4] = mat[4];
839         dest[5] = mat[7];
840         dest[6] = mat[2];
841         dest[7] = mat[5];
842         dest[8] = mat[8];
843         return dest;
844     };
845
846     /**
847      * Copies the elements of a mat3 into the upper 3x3 elements of a mat4
848      *
849      * @param {mat3} mat mat3 containing values to copy
850      * @param {mat4} [dest] mat4 receiving copied values
851      *
852      * @returns {mat4} dest if specified, a new mat4 otherwise
853      */
854     mat3.toMat4 = function (mat, dest) {
855         if (!dest) { dest = mat4.create(); }
856
857         dest[15] = 1;
858         dest[14] = 0;
859         dest[13] = 0;
860         dest[12] = 0;
861
862         dest[11] = 0;
863         dest[10] = mat[8];
864         dest[9] = mat[7];
865         dest[8] = mat[6];
866
867         dest[7] = 0;
868         dest[6] = mat[5];
869         dest[5] = mat[4];
870         dest[4] = mat[3];
871
872         dest[3] = 0;
873         dest[2] = mat[2];
874         dest[1] = mat[1];
875         dest[0] = mat[0];
876
877         return dest;
878     };
879
880     /**
881      * Returns a string representation of a mat3
882      *
883      * @param {mat3} mat mat3 to represent as a string
884      *
885      * @param {string} String representation of mat
886      */
887     mat3.str = function (mat) {
888         return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] +
889             ', ' + mat[3] + ', ' + mat[4] + ', ' + mat[5] +
890             ', ' + mat[6] + ', ' + mat[7] + ', ' + mat[8] + ']';
891     };
892
893     /**
894      * @class 4x4 Matrix
895      * @name mat4
896      */
897     var mat4 = {};
898
899     /**
900      * Creates a new instance of a mat4 using the default array type
901      * Any javascript array-like object containing at least 16 numeric elements can serve as a mat4
902      *
903      * @param {mat4} [mat] mat4 containing values to initialize with
904      *
905      * @returns {mat4} New mat4
906      */
907     mat4.create = function (mat) {
908         var dest = new MatrixArray(16);
909
910         if (mat) {
911             dest[0] = mat[0];
912             dest[1] = mat[1];
913             dest[2] = mat[2];
914             dest[3] = mat[3];
915             dest[4] = mat[4];
916             dest[5] = mat[5];
917             dest[6] = mat[6];
918             dest[7] = mat[7];
919             dest[8] = mat[8];
920             dest[9] = mat[9];
921             dest[10] = mat[10];
922             dest[11] = mat[11];
923             dest[12] = mat[12];
924             dest[13] = mat[13];
925             dest[14] = mat[14];
926             dest[15] = mat[15];
927         }
928
929         return dest;
930     };
931
932     /**
933      * Creates a new instance of a mat4, initializing it with the given arguments
934      *
935      * @param {number} m00
936      * @param {number} m01
937      * @param {number} m02
938      * @param {number} m03
939      * @param {number} m10
940      * @param {number} m11
941      * @param {number} m12
942      * @param {number} m13
943      * @param {number} m20
944      * @param {number} m21
945      * @param {number} m22
946      * @param {number} m23
947      * @param {number} m30
948      * @param {number} m31
949      * @param {number} m32
950      * @param {number} m33
951
952      * @returns {mat4} New mat4
953      */
954     mat4.createFrom = function (m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
955         var dest = new MatrixArray(16);
956
957         dest[0] = m00;
958         dest[1] = m01;
959         dest[2] = m02;
960         dest[3] = m03;
961         dest[4] = m10;
962         dest[5] = m11;
963         dest[6] = m12;
964         dest[7] = m13;
965         dest[8] = m20;
966         dest[9] = m21;
967         dest[10] = m22;
968         dest[11] = m23;
969         dest[12] = m30;
970         dest[13] = m31;
971         dest[14] = m32;
972         dest[15] = m33;
973
974         return dest;
975     };
976
977     /**
978      * Copies the values of one mat4 to another
979      *
980      * @param {mat4} mat mat4 containing values to copy
981      * @param {mat4} dest mat4 receiving copied values
982      *
983      * @returns {mat4} dest
984      */
985     mat4.set = function (mat, dest) {
986         dest[0] = mat[0];
987         dest[1] = mat[1];
988         dest[2] = mat[2];
989         dest[3] = mat[3];
990         dest[4] = mat[4];
991         dest[5] = mat[5];
992         dest[6] = mat[6];
993         dest[7] = mat[7];
994         dest[8] = mat[8];
995         dest[9] = mat[9];
996         dest[10] = mat[10];
997         dest[11] = mat[11];
998         dest[12] = mat[12];
999         dest[13] = mat[13];
1000         dest[14] = mat[14];
1001         dest[15] = mat[15];
1002         return dest;
1003     };
1004
1005     /**
1006      * Compares two matrices for equality within a certain margin of error
1007      *
1008      * @param {mat4} a First matrix
1009      * @param {mat4} b Second matrix
1010      *
1011      * @returns {Boolean} True if a is equivalent to b
1012      */
1013     mat4.equal = function (a, b) {
1014         return a === b || (
1015             Math.abs(a[0] - b[0]) < FLOAT_EPSILON &&
1016             Math.abs(a[1] - b[1]) < FLOAT_EPSILON &&
1017             Math.abs(a[2] - b[2]) < FLOAT_EPSILON &&
1018             Math.abs(a[3] - b[3]) < FLOAT_EPSILON &&
1019             Math.abs(a[4] - b[4]) < FLOAT_EPSILON &&
1020             Math.abs(a[5] - b[5]) < FLOAT_EPSILON &&
1021             Math.abs(a[6] - b[6]) < FLOAT_EPSILON &&
1022             Math.abs(a[7] - b[7]) < FLOAT_EPSILON &&
1023             Math.abs(a[8] - b[8]) < FLOAT_EPSILON &&
1024             Math.abs(a[9] - b[9]) < FLOAT_EPSILON &&
1025             Math.abs(a[10] - b[10]) < FLOAT_EPSILON &&
1026             Math.abs(a[11] - b[11]) < FLOAT_EPSILON &&
1027             Math.abs(a[12] - b[12]) < FLOAT_EPSILON &&
1028             Math.abs(a[13] - b[13]) < FLOAT_EPSILON &&
1029             Math.abs(a[14] - b[14]) < FLOAT_EPSILON &&
1030             Math.abs(a[15] - b[15]) < FLOAT_EPSILON
1031         );
1032     };
1033
1034     /**
1035      * Sets a mat4 to an identity matrix
1036      *
1037      * @param {mat4} dest mat4 to set
1038      *
1039      * @returns {mat4} dest
1040      */
1041     mat4.identity = function (dest) {
1042         if (!dest) { dest = mat4.create(); }
1043         dest[0] = 1;
1044         dest[1] = 0;
1045         dest[2] = 0;
1046         dest[3] = 0;
1047         dest[4] = 0;
1048         dest[5] = 1;
1049         dest[6] = 0;
1050         dest[7] = 0;
1051         dest[8] = 0;
1052         dest[9] = 0;
1053         dest[10] = 1;
1054         dest[11] = 0;
1055         dest[12] = 0;
1056         dest[13] = 0;
1057         dest[14] = 0;
1058         dest[15] = 1;
1059         return dest;
1060     };
1061
1062     /**
1063      * Transposes a mat4 (flips the values over the diagonal)
1064      *
1065      * @param {mat4} mat mat4 to transpose
1066      * @param {mat4} [dest] mat4 receiving transposed values. If not specified result is written to mat
1067      *
1068      * @param {mat4} dest is specified, mat otherwise
1069      */
1070     mat4.transpose = function (mat, dest) {
1071         // If we are transposing ourselves we can skip a few steps but have to cache some values
1072         if (!dest || mat === dest) {
1073             var a01 = mat[1], a02 = mat[2], a03 = mat[3],
1074                 a12 = mat[6], a13 = mat[7],
1075                 a23 = mat[11];
1076
1077             mat[1] = mat[4];
1078             mat[2] = mat[8];
1079             mat[3] = mat[12];
1080             mat[4] = a01;
1081             mat[6] = mat[9];
1082             mat[7] = mat[13];
1083             mat[8] = a02;
1084             mat[9] = a12;
1085             mat[11] = mat[14];
1086             mat[12] = a03;
1087             mat[13] = a13;
1088             mat[14] = a23;
1089             return mat;
1090         }
1091
1092         dest[0] = mat[0];
1093         dest[1] = mat[4];
1094         dest[2] = mat[8];
1095         dest[3] = mat[12];
1096         dest[4] = mat[1];
1097         dest[5] = mat[5];
1098         dest[6] = mat[9];
1099         dest[7] = mat[13];
1100         dest[8] = mat[2];
1101         dest[9] = mat[6];
1102         dest[10] = mat[10];
1103         dest[11] = mat[14];
1104         dest[12] = mat[3];
1105         dest[13] = mat[7];
1106         dest[14] = mat[11];
1107         dest[15] = mat[15];
1108         return dest;
1109     };
1110
1111     /**
1112      * Calculates the determinant of a mat4
1113      *
1114      * @param {mat4} mat mat4 to calculate determinant of
1115      *
1116      * @returns {number} determinant of mat
1117      */
1118     mat4.determinant = function (mat) {
1119         // Cache the matrix values (makes for huge speed increases!)
1120         var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3],
1121             a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7],
1122             a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11],
1123             a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
1124
1125         return (a30 * a21 * a12 * a03 - a20 * a31 * a12 * a03 - a30 * a11 * a22 * a03 + a10 * a31 * a22 * a03 +
1126                 a20 * a11 * a32 * a03 - a10 * a21 * a32 * a03 - a30 * a21 * a02 * a13 + a20 * a31 * a02 * a13 +
1127                 a30 * a01 * a22 * a13 - a00 * a31 * a22 * a13 - a20 * a01 * a32 * a13 + a00 * a21 * a32 * a13 +
1128                 a30 * a11 * a02 * a23 - a10 * a31 * a02 * a23 - a30 * a01 * a12 * a23 + a00 * a31 * a12 * a23 +
1129                 a10 * a01 * a32 * a23 - a00 * a11 * a32 * a23 - a20 * a11 * a02 * a33 + a10 * a21 * a02 * a33 +
1130                 a20 * a01 * a12 * a33 - a00 * a21 * a12 * a33 - a10 * a01 * a22 * a33 + a00 * a11 * a22 * a33);
1131     };
1132
1133     /**
1134      * Calculates the inverse matrix of a mat4
1135      *
1136      * @param {mat4} mat mat4 to calculate inverse of
1137      * @param {mat4} [dest] mat4 receiving inverse matrix. If not specified result is written to mat
1138      *
1139      * @param {mat4} dest is specified, mat otherwise, null if matrix cannot be inverted
1140      */
1141     mat4.inverse = function (mat, dest) {
1142         if (!dest) { dest = mat; }
1143
1144         // Cache the matrix values (makes for huge speed increases!)
1145         var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3],
1146             a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7],
1147             a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11],
1148             a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15],
1149
1150             b00 = a00 * a11 - a01 * a10,
1151             b01 = a00 * a12 - a02 * a10,
1152             b02 = a00 * a13 - a03 * a10,
1153             b03 = a01 * a12 - a02 * a11,
1154             b04 = a01 * a13 - a03 * a11,
1155             b05 = a02 * a13 - a03 * a12,
1156             b06 = a20 * a31 - a21 * a30,
1157             b07 = a20 * a32 - a22 * a30,
1158             b08 = a20 * a33 - a23 * a30,
1159             b09 = a21 * a32 - a22 * a31,
1160             b10 = a21 * a33 - a23 * a31,
1161             b11 = a22 * a33 - a23 * a32,
1162
1163             d = (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06),
1164             invDet;
1165
1166             // Calculate the determinant
1167             if (!d) { return null; }
1168             invDet = 1 / d;
1169
1170         dest[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;
1171         dest[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;
1172         dest[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;
1173         dest[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;
1174         dest[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;
1175         dest[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;
1176         dest[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;
1177         dest[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;
1178         dest[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;
1179         dest[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;
1180         dest[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;
1181         dest[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;
1182         dest[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;
1183         dest[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;
1184         dest[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;
1185         dest[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;
1186
1187         return dest;
1188     };
1189
1190     /**
1191      * Copies the upper 3x3 elements of a mat4 into another mat4
1192      *
1193      * @param {mat4} mat mat4 containing values to copy
1194      * @param {mat4} [dest] mat4 receiving copied values
1195      *
1196      * @returns {mat4} dest is specified, a new mat4 otherwise
1197      */
1198     mat4.toRotationMat = function (mat, dest) {
1199         if (!dest) { dest = mat4.create(); }
1200
1201         dest[0] = mat[0];
1202         dest[1] = mat[1];
1203         dest[2] = mat[2];
1204         dest[3] = mat[3];
1205         dest[4] = mat[4];
1206         dest[5] = mat[5];
1207         dest[6] = mat[6];
1208         dest[7] = mat[7];
1209         dest[8] = mat[8];
1210         dest[9] = mat[9];
1211         dest[10] = mat[10];
1212         dest[11] = mat[11];
1213         dest[12] = 0;
1214         dest[13] = 0;
1215         dest[14] = 0;
1216         dest[15] = 1;
1217
1218         return dest;
1219     };
1220
1221     /**
1222      * Copies the upper 3x3 elements of a mat4 into a mat3
1223      *
1224      * @param {mat4} mat mat4 containing values to copy
1225      * @param {mat3} [dest] mat3 receiving copied values
1226      *
1227      * @returns {mat3} dest is specified, a new mat3 otherwise
1228      */
1229     mat4.toMat3 = function (mat, dest) {
1230         if (!dest) { dest = mat3.create(); }
1231
1232         dest[0] = mat[0];
1233         dest[1] = mat[1];
1234         dest[2] = mat[2];
1235         dest[3] = mat[4];
1236         dest[4] = mat[5];
1237         dest[5] = mat[6];
1238         dest[6] = mat[8];
1239         dest[7] = mat[9];
1240         dest[8] = mat[10];
1241
1242         return dest;
1243     };
1244
1245     /**
1246      * Calculates the inverse of the upper 3x3 elements of a mat4 and copies the result into a mat3
1247      * The resulting matrix is useful for calculating transformed normals
1248      *
1249      * Params:
1250      * @param {mat4} mat mat4 containing values to invert and copy
1251      * @param {mat3} [dest] mat3 receiving values
1252      *
1253      * @returns {mat3} dest is specified, a new mat3 otherwise, null if the matrix cannot be inverted
1254      */
1255     mat4.toInverseMat3 = function (mat, dest) {
1256         // Cache the matrix values (makes for huge speed increases!)
1257         var a00 = mat[0], a01 = mat[1], a02 = mat[2],
1258             a10 = mat[4], a11 = mat[5], a12 = mat[6],
1259             a20 = mat[8], a21 = mat[9], a22 = mat[10],
1260
1261             b01 = a22 * a11 - a12 * a21,
1262             b11 = -a22 * a10 + a12 * a20,
1263             b21 = a21 * a10 - a11 * a20,
1264
1265             d = a00 * b01 + a01 * b11 + a02 * b21,
1266             id;
1267
1268         if (!d) { return null; }
1269         id = 1 / d;
1270
1271         if (!dest) { dest = mat3.create(); }
1272
1273         dest[0] = b01 * id;
1274         dest[1] = (-a22 * a01 + a02 * a21) * id;
1275         dest[2] = (a12 * a01 - a02 * a11) * id;
1276         dest[3] = b11 * id;
1277         dest[4] = (a22 * a00 - a02 * a20) * id;
1278         dest[5] = (-a12 * a00 + a02 * a10) * id;
1279         dest[6] = b21 * id;
1280         dest[7] = (-a21 * a00 + a01 * a20) * id;
1281         dest[8] = (a11 * a00 - a01 * a10) * id;
1282
1283         return dest;
1284     };
1285
1286     /**
1287      * Performs a matrix multiplication
1288      *
1289      * @param {mat4} mat First operand
1290      * @param {mat4} mat2 Second operand
1291      * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1292      *
1293      * @returns {mat4} dest if specified, mat otherwise
1294      */
1295     mat4.multiply = function (mat, mat2, dest) {
1296         if (!dest) { dest = mat; }
1297
1298         // Cache the matrix values (makes for huge speed increases!)
1299         var a00 = mat[ 0], a01 = mat[ 1], a02 = mat[ 2], a03 = mat[3];
1300         var a10 = mat[ 4], a11 = mat[ 5], a12 = mat[ 6], a13 = mat[7];
1301         var a20 = mat[ 8], a21 = mat[ 9], a22 = mat[10], a23 = mat[11];
1302         var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
1303
1304         // Cache only the current line of the second matrix
1305         var b0  = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3];  
1306         dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
1307         dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
1308         dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
1309         dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
1310
1311         b0 = mat2[4];
1312         b1 = mat2[5];
1313         b2 = mat2[6];
1314         b3 = mat2[7];
1315         dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
1316         dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
1317         dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
1318         dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
1319
1320         b0 = mat2[8];
1321         b1 = mat2[9];
1322         b2 = mat2[10];
1323         b3 = mat2[11];
1324         dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
1325         dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
1326         dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
1327         dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
1328
1329         b0 = mat2[12];
1330         b1 = mat2[13];
1331         b2 = mat2[14];
1332         b3 = mat2[15];
1333         dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
1334         dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
1335         dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
1336         dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
1337
1338         return dest;
1339     };
1340
1341     /**
1342      * Transforms a vec3 with the given matrix
1343      * 4th vector component is implicitly '1'
1344      *
1345      * @param {mat4} mat mat4 to transform the vector with
1346      * @param {vec3} vec vec3 to transform
1347      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
1348      *
1349      * @returns {vec3} dest if specified, vec otherwise
1350      */
1351     mat4.multiplyVec3 = function (mat, vec, dest) {
1352         if (!dest) { dest = vec; }
1353
1354         var x = vec[0], y = vec[1], z = vec[2];
1355
1356         dest[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12];
1357         dest[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13];
1358         dest[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14];
1359
1360         return dest;
1361     };
1362
1363     /**
1364      * Transforms a vec4 with the given matrix
1365      *
1366      * @param {mat4} mat mat4 to transform the vector with
1367      * @param {vec4} vec vec4 to transform
1368      * @param {vec4} [dest] vec4 receiving operation result. If not specified result is written to vec
1369      *
1370      * @returns {vec4} dest if specified, vec otherwise
1371      */
1372     mat4.multiplyVec4 = function (mat, vec, dest) {
1373         if (!dest) { dest = vec; }
1374
1375         var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
1376
1377         dest[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12] * w;
1378         dest[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13] * w;
1379         dest[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14] * w;
1380         dest[3] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15] * w;
1381
1382         return dest;
1383     };
1384
1385     /**
1386      * Translates a matrix by the given vector
1387      *
1388      * @param {mat4} mat mat4 to translate
1389      * @param {vec3} vec vec3 specifying the translation
1390      * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1391      *
1392      * @returns {mat4} dest if specified, mat otherwise
1393      */
1394     mat4.translate = function (mat, vec, dest) {
1395         var x = vec[0], y = vec[1], z = vec[2],
1396             a00, a01, a02, a03,
1397             a10, a11, a12, a13,
1398             a20, a21, a22, a23;
1399
1400         if (!dest || mat === dest) {
1401             mat[12] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12];
1402             mat[13] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13];
1403             mat[14] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14];
1404             mat[15] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15];
1405             return mat;
1406         }
1407
1408         a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3];
1409         a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7];
1410         a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11];
1411
1412         dest[0] = a00; dest[1] = a01; dest[2] = a02; dest[3] = a03;
1413         dest[4] = a10; dest[5] = a11; dest[6] = a12; dest[7] = a13;
1414         dest[8] = a20; dest[9] = a21; dest[10] = a22; dest[11] = a23;
1415
1416         dest[12] = a00 * x + a10 * y + a20 * z + mat[12];
1417         dest[13] = a01 * x + a11 * y + a21 * z + mat[13];
1418         dest[14] = a02 * x + a12 * y + a22 * z + mat[14];
1419         dest[15] = a03 * x + a13 * y + a23 * z + mat[15];
1420         return dest;
1421     };
1422
1423     /**
1424      * Scales a matrix by the given vector
1425      *
1426      * @param {mat4} mat mat4 to scale
1427      * @param {vec3} vec vec3 specifying the scale for each axis
1428      * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1429      *
1430      * @param {mat4} dest if specified, mat otherwise
1431      */
1432     mat4.scale = function (mat, vec, dest) {
1433         var x = vec[0], y = vec[1], z = vec[2];
1434
1435         if (!dest || mat === dest) {
1436             mat[0] *= x;
1437             mat[1] *= x;
1438             mat[2] *= x;
1439             mat[3] *= x;
1440             mat[4] *= y;
1441             mat[5] *= y;
1442             mat[6] *= y;
1443             mat[7] *= y;
1444             mat[8] *= z;
1445             mat[9] *= z;
1446             mat[10] *= z;
1447             mat[11] *= z;
1448             return mat;
1449         }
1450
1451         dest[0] = mat[0] * x;
1452         dest[1] = mat[1] * x;
1453         dest[2] = mat[2] * x;
1454         dest[3] = mat[3] * x;
1455         dest[4] = mat[4] * y;
1456         dest[5] = mat[5] * y;
1457         dest[6] = mat[6] * y;
1458         dest[7] = mat[7] * y;
1459         dest[8] = mat[8] * z;
1460         dest[9] = mat[9] * z;
1461         dest[10] = mat[10] * z;
1462         dest[11] = mat[11] * z;
1463         dest[12] = mat[12];
1464         dest[13] = mat[13];
1465         dest[14] = mat[14];
1466         dest[15] = mat[15];
1467         return dest;
1468     };
1469
1470     /**
1471      * Rotates a matrix by the given angle around the specified axis
1472      * If rotating around a primary axis (X,Y,Z) one of the specialized rotation functions should be used instead for performance
1473      *
1474      * @param {mat4} mat mat4 to rotate
1475      * @param {number} angle Angle (in radians) to rotate
1476      * @param {vec3} axis vec3 representing the axis to rotate around
1477      * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1478      *
1479      * @returns {mat4} dest if specified, mat otherwise
1480      */
1481     mat4.rotate = function (mat, angle, axis, dest) {
1482         var x = axis[0], y = axis[1], z = axis[2],
1483             len = Math.sqrt(x * x + y * y + z * z),
1484             s, c, t,
1485             a00, a01, a02, a03,
1486             a10, a11, a12, a13,
1487             a20, a21, a22, a23,
1488             b00, b01, b02,
1489             b10, b11, b12,
1490             b20, b21, b22;
1491
1492         if (!len) { return null; }
1493         if (len !== 1) {
1494             len = 1 / len;
1495             x *= len;
1496             y *= len;
1497             z *= len;
1498         }
1499
1500         s = Math.sin(angle);
1501         c = Math.cos(angle);
1502         t = 1 - c;
1503
1504         a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3];
1505         a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7];
1506         a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11];
1507
1508         // Construct the elements of the rotation matrix
1509         b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
1510         b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
1511         b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
1512
1513         if (!dest) {
1514             dest = mat;
1515         } else if (mat !== dest) { // If the source and destination differ, copy the unchanged last row
1516             dest[12] = mat[12];
1517             dest[13] = mat[13];
1518             dest[14] = mat[14];
1519             dest[15] = mat[15];
1520         }
1521
1522         // Perform rotation-specific matrix multiplication
1523         dest[0] = a00 * b00 + a10 * b01 + a20 * b02;
1524         dest[1] = a01 * b00 + a11 * b01 + a21 * b02;
1525         dest[2] = a02 * b00 + a12 * b01 + a22 * b02;
1526         dest[3] = a03 * b00 + a13 * b01 + a23 * b02;
1527
1528         dest[4] = a00 * b10 + a10 * b11 + a20 * b12;
1529         dest[5] = a01 * b10 + a11 * b11 + a21 * b12;
1530         dest[6] = a02 * b10 + a12 * b11 + a22 * b12;
1531         dest[7] = a03 * b10 + a13 * b11 + a23 * b12;
1532
1533         dest[8] = a00 * b20 + a10 * b21 + a20 * b22;
1534         dest[9] = a01 * b20 + a11 * b21 + a21 * b22;
1535         dest[10] = a02 * b20 + a12 * b21 + a22 * b22;
1536         dest[11] = a03 * b20 + a13 * b21 + a23 * b22;
1537         return dest;
1538     };
1539
1540     /**
1541      * Rotates a matrix by the given angle around the X axis
1542      *
1543      * @param {mat4} mat mat4 to rotate
1544      * @param {number} angle Angle (in radians) to rotate
1545      * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1546      *
1547      * @returns {mat4} dest if specified, mat otherwise
1548      */
1549     mat4.rotateX = function (mat, angle, dest) {
1550         var s = Math.sin(angle),
1551             c = Math.cos(angle),
1552             a10 = mat[4],
1553             a11 = mat[5],
1554             a12 = mat[6],
1555             a13 = mat[7],
1556             a20 = mat[8],
1557             a21 = mat[9],
1558             a22 = mat[10],
1559             a23 = mat[11];
1560
1561         if (!dest) {
1562             dest = mat;
1563         } else if (mat !== dest) { // If the source and destination differ, copy the unchanged rows
1564             dest[0] = mat[0];
1565             dest[1] = mat[1];
1566             dest[2] = mat[2];
1567             dest[3] = mat[3];
1568
1569             dest[12] = mat[12];
1570             dest[13] = mat[13];
1571             dest[14] = mat[14];
1572             dest[15] = mat[15];
1573         }
1574
1575         // Perform axis-specific matrix multiplication
1576         dest[4] = a10 * c + a20 * s;
1577         dest[5] = a11 * c + a21 * s;
1578         dest[6] = a12 * c + a22 * s;
1579         dest[7] = a13 * c + a23 * s;
1580
1581         dest[8] = a10 * -s + a20 * c;
1582         dest[9] = a11 * -s + a21 * c;
1583         dest[10] = a12 * -s + a22 * c;
1584         dest[11] = a13 * -s + a23 * c;
1585         return dest;
1586     };
1587
1588     /**
1589      * Rotates a matrix by the given angle around the Y axis
1590      *
1591      * @param {mat4} mat mat4 to rotate
1592      * @param {number} angle Angle (in radians) to rotate
1593      * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1594      *
1595      * @returns {mat4} dest if specified, mat otherwise
1596      */
1597     mat4.rotateY = function (mat, angle, dest) {
1598         var s = Math.sin(angle),
1599             c = Math.cos(angle),
1600             a00 = mat[0],
1601             a01 = mat[1],
1602             a02 = mat[2],
1603             a03 = mat[3],
1604             a20 = mat[8],
1605             a21 = mat[9],
1606             a22 = mat[10],
1607             a23 = mat[11];
1608
1609         if (!dest) {
1610             dest = mat;
1611         } else if (mat !== dest) { // If the source and destination differ, copy the unchanged rows
1612             dest[4] = mat[4];
1613             dest[5] = mat[5];
1614             dest[6] = mat[6];
1615             dest[7] = mat[7];
1616
1617             dest[12] = mat[12];
1618             dest[13] = mat[13];
1619             dest[14] = mat[14];
1620             dest[15] = mat[15];
1621         }
1622
1623         // Perform axis-specific matrix multiplication
1624         dest[0] = a00 * c + a20 * -s;
1625         dest[1] = a01 * c + a21 * -s;
1626         dest[2] = a02 * c + a22 * -s;
1627         dest[3] = a03 * c + a23 * -s;
1628
1629         dest[8] = a00 * s + a20 * c;
1630         dest[9] = a01 * s + a21 * c;
1631         dest[10] = a02 * s + a22 * c;
1632         dest[11] = a03 * s + a23 * c;
1633         return dest;
1634     };
1635
1636     /**
1637      * Rotates a matrix by the given angle around the Z axis
1638      *
1639      * @param {mat4} mat mat4 to rotate
1640      * @param {number} angle Angle (in radians) to rotate
1641      * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1642      *
1643      * @returns {mat4} dest if specified, mat otherwise
1644      */
1645     mat4.rotateZ = function (mat, angle, dest) {
1646         var s = Math.sin(angle),
1647             c = Math.cos(angle),
1648             a00 = mat[0],
1649             a01 = mat[1],
1650             a02 = mat[2],
1651             a03 = mat[3],
1652             a10 = mat[4],
1653             a11 = mat[5],
1654             a12 = mat[6],
1655             a13 = mat[7];
1656
1657         if (!dest) {
1658             dest = mat;
1659         } else if (mat !== dest) { // If the source and destination differ, copy the unchanged last row
1660             dest[8] = mat[8];
1661             dest[9] = mat[9];
1662             dest[10] = mat[10];
1663             dest[11] = mat[11];
1664
1665             dest[12] = mat[12];
1666             dest[13] = mat[13];
1667             dest[14] = mat[14];
1668             dest[15] = mat[15];
1669         }
1670
1671         // Perform axis-specific matrix multiplication
1672         dest[0] = a00 * c + a10 * s;
1673         dest[1] = a01 * c + a11 * s;
1674         dest[2] = a02 * c + a12 * s;
1675         dest[3] = a03 * c + a13 * s;
1676
1677         dest[4] = a00 * -s + a10 * c;
1678         dest[5] = a01 * -s + a11 * c;
1679         dest[6] = a02 * -s + a12 * c;
1680         dest[7] = a03 * -s + a13 * c;
1681
1682         return dest;
1683     };
1684
1685     /**
1686      * Generates a frustum matrix with the given bounds
1687      *
1688      * @param {number} left Left bound of the frustum
1689      * @param {number} right Right bound of the frustum
1690      * @param {number} bottom Bottom bound of the frustum
1691      * @param {number} top Top bound of the frustum
1692      * @param {number} near Near bound of the frustum
1693      * @param {number} far Far bound of the frustum
1694      * @param {mat4} [dest] mat4 frustum matrix will be written into
1695      *
1696      * @returns {mat4} dest if specified, a new mat4 otherwise
1697      */
1698     mat4.frustum = function (left, right, bottom, top, near, far, dest) {
1699         if (!dest) { dest = mat4.create(); }
1700         var rl = (right - left),
1701             tb = (top - bottom),
1702             fn = (far - near);
1703         dest[0] = (near * 2) / rl;
1704         dest[1] = 0;
1705         dest[2] = 0;
1706         dest[3] = 0;
1707         dest[4] = 0;
1708         dest[5] = (near * 2) / tb;
1709         dest[6] = 0;
1710         dest[7] = 0;
1711         dest[8] = (right + left) / rl;
1712         dest[9] = (top + bottom) / tb;
1713         dest[10] = -(far + near) / fn;
1714         dest[11] = -1;
1715         dest[12] = 0;
1716         dest[13] = 0;
1717         dest[14] = -(far * near * 2) / fn;
1718         dest[15] = 0;
1719         return dest;
1720     };
1721
1722     /**
1723      * Generates a perspective projection matrix with the given bounds
1724      *
1725      * @param {number} fovy Vertical field of view
1726      * @param {number} aspect Aspect ratio. typically viewport width/height
1727      * @param {number} near Near bound of the frustum
1728      * @param {number} far Far bound of the frustum
1729      * @param {mat4} [dest] mat4 frustum matrix will be written into
1730      *
1731      * @returns {mat4} dest if specified, a new mat4 otherwise
1732      */
1733     mat4.perspective = function (fovy, aspect, near, far, dest) {
1734         var top = near * Math.tan(fovy * Math.PI / 360.0),
1735             right = top * aspect;
1736         return mat4.frustum(-right, right, -top, top, near, far, dest);
1737     };
1738
1739     /**
1740      * Generates a orthogonal projection matrix with the given bounds
1741      *
1742      * @param {number} left Left bound of the frustum
1743      * @param {number} right Right bound of the frustum
1744      * @param {number} bottom Bottom bound of the frustum
1745      * @param {number} top Top bound of the frustum
1746      * @param {number} near Near bound of the frustum
1747      * @param {number} far Far bound of the frustum
1748      * @param {mat4} [dest] mat4 frustum matrix will be written into
1749      *
1750      * @returns {mat4} dest if specified, a new mat4 otherwise
1751      */
1752     mat4.ortho = function (left, right, bottom, top, near, far, dest) {
1753         if (!dest) { dest = mat4.create(); }
1754         var rl = (right - left),
1755             tb = (top - bottom),
1756             fn = (far - near);
1757         dest[0] = 2 / rl;
1758         dest[1] = 0;
1759         dest[2] = 0;
1760         dest[3] = 0;
1761         dest[4] = 0;
1762         dest[5] = 2 / tb;
1763         dest[6] = 0;
1764         dest[7] = 0;
1765         dest[8] = 0;
1766         dest[9] = 0;
1767         dest[10] = -2 / fn;
1768         dest[11] = 0;
1769         dest[12] = -(left + right) / rl;
1770         dest[13] = -(top + bottom) / tb;
1771         dest[14] = -(far + near) / fn;
1772         dest[15] = 1;
1773         return dest;
1774     };
1775
1776     /**
1777      * Generates a look-at matrix with the given eye position, focal point, and up axis
1778      *
1779      * @param {vec3} eye Position of the viewer
1780      * @param {vec3} center Point the viewer is looking at
1781      * @param {vec3} up vec3 pointing "up"
1782      * @param {mat4} [dest] mat4 frustum matrix will be written into
1783      *
1784      * @returns {mat4} dest if specified, a new mat4 otherwise
1785      */
1786     mat4.lookAt = function (eye, center, up, dest) {
1787         if (!dest) { dest = mat4.create(); }
1788
1789         var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
1790             eyex = eye[0],
1791             eyey = eye[1],
1792             eyez = eye[2],
1793             upx = up[0],
1794             upy = up[1],
1795             upz = up[2],
1796             centerx = center[0],
1797             centery = center[1],
1798             centerz = center[2];
1799
1800         if (eyex === centerx && eyey === centery && eyez === centerz) {
1801             return mat4.identity(dest);
1802         }
1803
1804         //vec3.direction(eye, center, z);
1805         z0 = eyex - centerx;
1806         z1 = eyey - centery;
1807         z2 = eyez - centerz;
1808
1809         // normalize (no check needed for 0 because of early return)
1810         len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
1811         z0 *= len;
1812         z1 *= len;
1813         z2 *= len;
1814
1815         //vec3.normalize(vec3.cross(up, z, x));
1816         x0 = upy * z2 - upz * z1;
1817         x1 = upz * z0 - upx * z2;
1818         x2 = upx * z1 - upy * z0;
1819         len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
1820         if (!len) {
1821             x0 = 0;
1822             x1 = 0;
1823             x2 = 0;
1824         } else {
1825             len = 1 / len;
1826             x0 *= len;
1827             x1 *= len;
1828             x2 *= len;
1829         }
1830
1831         //vec3.normalize(vec3.cross(z, x, y));
1832         y0 = z1 * x2 - z2 * x1;
1833         y1 = z2 * x0 - z0 * x2;
1834         y2 = z0 * x1 - z1 * x0;
1835
1836         len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
1837         if (!len) {
1838             y0 = 0;
1839             y1 = 0;
1840             y2 = 0;
1841         } else {
1842             len = 1 / len;
1843             y0 *= len;
1844             y1 *= len;
1845             y2 *= len;
1846         }
1847
1848         dest[0] = x0;
1849         dest[1] = y0;
1850         dest[2] = z0;
1851         dest[3] = 0;
1852         dest[4] = x1;
1853         dest[5] = y1;
1854         dest[6] = z1;
1855         dest[7] = 0;
1856         dest[8] = x2;
1857         dest[9] = y2;
1858         dest[10] = z2;
1859         dest[11] = 0;
1860         dest[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
1861         dest[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
1862         dest[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
1863         dest[15] = 1;
1864
1865         return dest;
1866     };
1867
1868     /**
1869      * Creates a matrix from a quaternion rotation and vector translation
1870      * This is equivalent to (but much faster than):
1871      *
1872      *     mat4.identity(dest);
1873      *     mat4.translate(dest, vec);
1874      *     var quatMat = mat4.create();
1875      *     quat4.toMat4(quat, quatMat);
1876      *     mat4.multiply(dest, quatMat);
1877      *
1878      * @param {quat4} quat Rotation quaternion
1879      * @param {vec3} vec Translation vector
1880      * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to a new mat4
1881      *
1882      * @returns {mat4} dest if specified, a new mat4 otherwise
1883      */
1884     mat4.fromRotationTranslation = function (quat, vec, dest) {
1885         if (!dest) { dest = mat4.create(); }
1886
1887         // Quaternion math
1888         var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
1889             x2 = x + x,
1890             y2 = y + y,
1891             z2 = z + z,
1892
1893             xx = x * x2,
1894             xy = x * y2,
1895             xz = x * z2,
1896             yy = y * y2,
1897             yz = y * z2,
1898             zz = z * z2,
1899             wx = w * x2,
1900             wy = w * y2,
1901             wz = w * z2;
1902
1903         dest[0] = 1 - (yy + zz);
1904         dest[1] = xy + wz;
1905         dest[2] = xz - wy;
1906         dest[3] = 0;
1907         dest[4] = xy - wz;
1908         dest[5] = 1 - (xx + zz);
1909         dest[6] = yz + wx;
1910         dest[7] = 0;
1911         dest[8] = xz + wy;
1912         dest[9] = yz - wx;
1913         dest[10] = 1 - (xx + yy);
1914         dest[11] = 0;
1915         dest[12] = vec[0];
1916         dest[13] = vec[1];
1917         dest[14] = vec[2];
1918         dest[15] = 1;
1919         
1920         return dest;
1921     };
1922
1923     /**
1924      * Returns a string representation of a mat4
1925      *
1926      * @param {mat4} mat mat4 to represent as a string
1927      *
1928      * @returns {string} String representation of mat
1929      */
1930     mat4.str = function (mat) {
1931         return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + ', ' + mat[3] +
1932             ', ' + mat[4] + ', ' + mat[5] + ', ' + mat[6] + ', ' + mat[7] +
1933             ', ' + mat[8] + ', ' + mat[9] + ', ' + mat[10] + ', ' + mat[11] +
1934             ', ' + mat[12] + ', ' + mat[13] + ', ' + mat[14] + ', ' + mat[15] + ']';
1935     };
1936
1937     /**
1938      * @class Quaternion
1939      * @name quat4
1940      */
1941     var quat4 = {};
1942
1943     /**
1944      * Creates a new instance of a quat4 using the default array type
1945      * Any javascript array containing at least 4 numeric elements can serve as a quat4
1946      *
1947      * @param {quat4} [quat] quat4 containing values to initialize with
1948      *
1949      * @returns {quat4} New quat4
1950      */
1951     quat4.create = function (quat) {
1952         var dest = new MatrixArray(4);
1953
1954         if (quat) {
1955             dest[0] = quat[0];
1956             dest[1] = quat[1];
1957             dest[2] = quat[2];
1958             dest[3] = quat[3];
1959         } else {
1960             dest[0] = dest[1] = dest[2] = dest[3] = 0;
1961         }
1962
1963         return dest;
1964     };
1965
1966     /**
1967      * Creates a new instance of a quat4, initializing it with the given arguments
1968      *
1969      * @param {number} x X value
1970      * @param {number} y Y value
1971      * @param {number} z Z value
1972      * @param {number} w W value
1973
1974      * @returns {quat4} New quat4
1975      */
1976     quat4.createFrom = function (x, y, z, w) {
1977         var dest = new MatrixArray(4);
1978
1979         dest[0] = x;
1980         dest[1] = y;
1981         dest[2] = z;
1982         dest[3] = w;
1983
1984         return dest;
1985     };
1986
1987     /**
1988      * Copies the values of one quat4 to another
1989      *
1990      * @param {quat4} quat quat4 containing values to copy
1991      * @param {quat4} dest quat4 receiving copied values
1992      *
1993      * @returns {quat4} dest
1994      */
1995     quat4.set = function (quat, dest) {
1996         dest[0] = quat[0];
1997         dest[1] = quat[1];
1998         dest[2] = quat[2];
1999         dest[3] = quat[3];
2000
2001         return dest;
2002     };
2003
2004     /**
2005      * Compares two quaternions for equality within a certain margin of error
2006      *
2007      * @param {quat4} a First vector
2008      * @param {quat4} b Second vector
2009      *
2010      * @returns {Boolean} True if a is equivalent to b
2011      */
2012     quat4.equal = function (a, b) {
2013         return a === b || (
2014             Math.abs(a[0] - b[0]) < FLOAT_EPSILON &&
2015             Math.abs(a[1] - b[1]) < FLOAT_EPSILON &&
2016             Math.abs(a[2] - b[2]) < FLOAT_EPSILON &&
2017             Math.abs(a[3] - b[3]) < FLOAT_EPSILON
2018         );
2019     };
2020
2021     /**
2022      * Creates a new identity Quat4
2023      *
2024      * @param {quat4} [dest] quat4 receiving copied values
2025      *
2026      * @returns {quat4} dest is specified, new quat4 otherwise
2027      */
2028     quat4.identity = function (dest) {
2029         if (!dest) { dest = quat4.create(); }
2030         dest[0] = 0;
2031         dest[1] = 0;
2032         dest[2] = 0;
2033         dest[3] = 1;
2034         return dest;
2035     };
2036
2037     var identityQuat4 = quat4.identity();
2038
2039     /**
2040      * Calculates the W component of a quat4 from the X, Y, and Z components.
2041      * Assumes that quaternion is 1 unit in length.
2042      * Any existing W component will be ignored.
2043      *
2044      * @param {quat4} quat quat4 to calculate W component of
2045      * @param {quat4} [dest] quat4 receiving calculated values. If not specified result is written to quat
2046      *
2047      * @returns {quat4} dest if specified, quat otherwise
2048      */
2049     quat4.calculateW = function (quat, dest) {
2050         var x = quat[0], y = quat[1], z = quat[2];
2051
2052         if (!dest || quat === dest) {
2053             quat[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
2054             return quat;
2055         }
2056         dest[0] = x;
2057         dest[1] = y;
2058         dest[2] = z;
2059         dest[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
2060         return dest;
2061     };
2062
2063     /**
2064      * Calculates the dot product of two quaternions
2065      *
2066      * @param {quat4} quat First operand
2067      * @param {quat4} quat2 Second operand
2068      *
2069      * @return {number} Dot product of quat and quat2
2070      */
2071     quat4.dot = function(quat, quat2){
2072         return quat[0]*quat2[0] + quat[1]*quat2[1] + quat[2]*quat2[2] + quat[3]*quat2[3];
2073     };
2074
2075     /**
2076      * Calculates the inverse of a quat4
2077      *
2078      * @param {quat4} quat quat4 to calculate inverse of
2079      * @param {quat4} [dest] quat4 receiving inverse values. If not specified result is written to quat
2080      *
2081      * @returns {quat4} dest if specified, quat otherwise
2082      */
2083     quat4.inverse = function(quat, dest) {
2084         var q0 = quat[0], q1 = quat[1], q2 = quat[2], q3 = quat[3],
2085             dot = q0*q0 + q1*q1 + q2*q2 + q3*q3,
2086             invDot = dot ? 1.0/dot : 0;
2087         
2088         // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
2089         
2090         if(!dest || quat === dest) {
2091             quat[0] *= -invDot;
2092             quat[1] *= -invDot;
2093             quat[2] *= -invDot;
2094             quat[3] *= invDot;
2095             return quat;
2096         }
2097         dest[0] = -quat[0]*invDot;
2098         dest[1] = -quat[1]*invDot;
2099         dest[2] = -quat[2]*invDot;
2100         dest[3] = quat[3]*invDot;
2101         return dest;
2102     };
2103
2104
2105     /**
2106      * Calculates the conjugate of a quat4
2107      * If the quaternion is normalized, this function is faster than quat4.inverse and produces the same result.
2108      *
2109      * @param {quat4} quat quat4 to calculate conjugate of
2110      * @param {quat4} [dest] quat4 receiving conjugate values. If not specified result is written to quat
2111      *
2112      * @returns {quat4} dest if specified, quat otherwise
2113      */
2114     quat4.conjugate = function (quat, dest) {
2115         if (!dest || quat === dest) {
2116             quat[0] *= -1;
2117             quat[1] *= -1;
2118             quat[2] *= -1;
2119             return quat;
2120         }
2121         dest[0] = -quat[0];
2122         dest[1] = -quat[1];
2123         dest[2] = -quat[2];
2124         dest[3] = quat[3];
2125         return dest;
2126     };
2127
2128     /**
2129      * Calculates the length of a quat4
2130      *
2131      * Params:
2132      * @param {quat4} quat quat4 to calculate length of
2133      *
2134      * @returns Length of quat
2135      */
2136     quat4.length = function (quat) {
2137         var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
2138         return Math.sqrt(x * x + y * y + z * z + w * w);
2139     };
2140
2141     /**
2142      * Generates a unit quaternion of the same direction as the provided quat4
2143      * If quaternion length is 0, returns [0, 0, 0, 0]
2144      *
2145      * @param {quat4} quat quat4 to normalize
2146      * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
2147      *
2148      * @returns {quat4} dest if specified, quat otherwise
2149      */
2150     quat4.normalize = function (quat, dest) {
2151         if (!dest) { dest = quat; }
2152
2153         var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
2154             len = Math.sqrt(x * x + y * y + z * z + w * w);
2155         if (len === 0) {
2156             dest[0] = 0;
2157             dest[1] = 0;
2158             dest[2] = 0;
2159             dest[3] = 0;
2160             return dest;
2161         }
2162         len = 1 / len;
2163         dest[0] = x * len;
2164         dest[1] = y * len;
2165         dest[2] = z * len;
2166         dest[3] = w * len;
2167
2168         return dest;
2169     };
2170
2171     /**
2172      * Performs quaternion addition
2173      *
2174      * @param {quat4} quat First operand
2175      * @param {quat4} quat2 Second operand
2176      * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
2177      *
2178      * @returns {quat4} dest if specified, quat otherwise
2179      */
2180     quat4.add = function (quat, quat2, dest) {
2181         if(!dest || quat === dest) {
2182             quat[0] += quat2[0];
2183             quat[1] += quat2[1];
2184             quat[2] += quat2[2];
2185             quat[3] += quat2[3];
2186             return quat;
2187         }
2188         dest[0] = quat[0]+quat2[0];
2189         dest[1] = quat[1]+quat2[1];
2190         dest[2] = quat[2]+quat2[2];
2191         dest[3] = quat[3]+quat2[3];
2192         return dest;
2193     };
2194
2195     /**
2196      * Performs a quaternion multiplication
2197      *
2198      * @param {quat4} quat First operand
2199      * @param {quat4} quat2 Second operand
2200      * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
2201      *
2202      * @returns {quat4} dest if specified, quat otherwise
2203      */
2204     quat4.multiply = function (quat, quat2, dest) {
2205         if (!dest) { dest = quat; }
2206
2207         var qax = quat[0], qay = quat[1], qaz = quat[2], qaw = quat[3],
2208             qbx = quat2[0], qby = quat2[1], qbz = quat2[2], qbw = quat2[3];
2209
2210         dest[0] = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
2211         dest[1] = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
2212         dest[2] = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
2213         dest[3] = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
2214
2215         return dest;
2216     };
2217
2218     /**
2219      * Transforms a vec3 with the given quaternion
2220      *
2221      * @param {quat4} quat quat4 to transform the vector with
2222      * @param {vec3} vec vec3 to transform
2223      * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
2224      *
2225      * @returns dest if specified, vec otherwise
2226      */
2227     quat4.multiplyVec3 = function (quat, vec, dest) {
2228         if (!dest) { dest = vec; }
2229
2230         var x = vec[0], y = vec[1], z = vec[2],
2231             qx = quat[0], qy = quat[1], qz = quat[2], qw = quat[3],
2232
2233             // calculate quat * vec
2234             ix = qw * x + qy * z - qz * y,
2235             iy = qw * y + qz * x - qx * z,
2236             iz = qw * z + qx * y - qy * x,
2237             iw = -qx * x - qy * y - qz * z;
2238
2239         // calculate result * inverse quat
2240         dest[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
2241         dest[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
2242         dest[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
2243
2244         return dest;
2245     };
2246
2247     /**
2248      * Multiplies the components of a quaternion by a scalar value
2249      *
2250      * @param {quat4} quat to scale
2251      * @param {number} val Value to scale by
2252      * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
2253      *
2254      * @returns {quat4} dest if specified, quat otherwise
2255      */
2256     quat4.scale = function (quat, val, dest) {
2257         if(!dest || quat === dest) {
2258             quat[0] *= val;
2259             quat[1] *= val;
2260             quat[2] *= val;
2261             quat[3] *= val;
2262             return quat;
2263         }
2264         dest[0] = quat[0]*val;
2265         dest[1] = quat[1]*val;
2266         dest[2] = quat[2]*val;
2267         dest[3] = quat[3]*val;
2268         return dest;
2269     };
2270
2271     /**
2272      * Calculates a 3x3 matrix from the given quat4
2273      *
2274      * @param {quat4} quat quat4 to create matrix from
2275      * @param {mat3} [dest] mat3 receiving operation result
2276      *
2277      * @returns {mat3} dest if specified, a new mat3 otherwise
2278      */
2279     quat4.toMat3 = function (quat, dest) {
2280         if (!dest) { dest = mat3.create(); }
2281
2282         var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
2283             x2 = x + x,
2284             y2 = y + y,
2285             z2 = z + z,
2286
2287             xx = x * x2,
2288             xy = x * y2,
2289             xz = x * z2,
2290             yy = y * y2,
2291             yz = y * z2,
2292             zz = z * z2,
2293             wx = w * x2,
2294             wy = w * y2,
2295             wz = w * z2;
2296
2297         dest[0] = 1 - (yy + zz);
2298         dest[1] = xy + wz;
2299         dest[2] = xz - wy;
2300
2301         dest[3] = xy - wz;
2302         dest[4] = 1 - (xx + zz);
2303         dest[5] = yz + wx;
2304
2305         dest[6] = xz + wy;
2306         dest[7] = yz - wx;
2307         dest[8] = 1 - (xx + yy);
2308
2309         return dest;
2310     };
2311
2312     /**
2313      * Calculates a 4x4 matrix from the given quat4
2314      *
2315      * @param {quat4} quat quat4 to create matrix from
2316      * @param {mat4} [dest] mat4 receiving operation result
2317      *
2318      * @returns {mat4} dest if specified, a new mat4 otherwise
2319      */
2320     quat4.toMat4 = function (quat, dest) {
2321         if (!dest) { dest = mat4.create(); }
2322
2323         var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
2324             x2 = x + x,
2325             y2 = y + y,
2326             z2 = z + z,
2327
2328             xx = x * x2,
2329             xy = x * y2,
2330             xz = x * z2,
2331             yy = y * y2,
2332             yz = y * z2,
2333             zz = z * z2,
2334             wx = w * x2,
2335             wy = w * y2,
2336             wz = w * z2;
2337
2338         dest[0] = 1 - (yy + zz);
2339         dest[1] = xy + wz;
2340         dest[2] = xz - wy;
2341         dest[3] = 0;
2342
2343         dest[4] = xy - wz;
2344         dest[5] = 1 - (xx + zz);
2345         dest[6] = yz + wx;
2346         dest[7] = 0;
2347
2348         dest[8] = xz + wy;
2349         dest[9] = yz - wx;
2350         dest[10] = 1 - (xx + yy);
2351         dest[11] = 0;
2352
2353         dest[12] = 0;
2354         dest[13] = 0;
2355         dest[14] = 0;
2356         dest[15] = 1;
2357
2358         return dest;
2359     };
2360
2361     /**
2362      * Performs a spherical linear interpolation between two quat4
2363      *
2364      * @param {quat4} quat First quaternion
2365      * @param {quat4} quat2 Second quaternion
2366      * @param {number} slerp Interpolation amount between the two inputs
2367      * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
2368      *
2369      * @returns {quat4} dest if specified, quat otherwise
2370      */
2371     quat4.slerp = function (quat, quat2, slerp, dest) {
2372         if (!dest) { dest = quat; }
2373
2374         var cosHalfTheta = quat[0] * quat2[0] + quat[1] * quat2[1] + quat[2] * quat2[2] + quat[3] * quat2[3],
2375             halfTheta,
2376             sinHalfTheta,
2377             ratioA,
2378             ratioB;
2379
2380         if (Math.abs(cosHalfTheta) >= 1.0) {
2381             if (dest !== quat) {
2382                 dest[0] = quat[0];
2383                 dest[1] = quat[1];
2384                 dest[2] = quat[2];
2385                 dest[3] = quat[3];
2386             }
2387             return dest;
2388         }
2389
2390         halfTheta = Math.acos(cosHalfTheta);
2391         sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
2392
2393         if (Math.abs(sinHalfTheta) < 0.001) {
2394             dest[0] = (quat[0] * 0.5 + quat2[0] * 0.5);
2395             dest[1] = (quat[1] * 0.5 + quat2[1] * 0.5);
2396             dest[2] = (quat[2] * 0.5 + quat2[2] * 0.5);
2397             dest[3] = (quat[3] * 0.5 + quat2[3] * 0.5);
2398             return dest;
2399         }
2400
2401         ratioA = Math.sin((1 - slerp) * halfTheta) / sinHalfTheta;
2402         ratioB = Math.sin(slerp * halfTheta) / sinHalfTheta;
2403
2404         dest[0] = (quat[0] * ratioA + quat2[0] * ratioB);
2405         dest[1] = (quat[1] * ratioA + quat2[1] * ratioB);
2406         dest[2] = (quat[2] * ratioA + quat2[2] * ratioB);
2407         dest[3] = (quat[3] * ratioA + quat2[3] * ratioB);
2408
2409         return dest;
2410     };
2411
2412     /**
2413      * Creates a quaternion from the given 3x3 rotation matrix.
2414      * If dest is omitted, a new quaternion will be created.
2415      *
2416      * @param {mat3}  mat    the rotation matrix
2417      * @param {quat4} [dest] an optional receiving quaternion
2418      *
2419      * @returns {quat4} the quaternion constructed from the rotation matrix
2420      *
2421      */
2422     quat4.fromRotationMatrix = function(mat, dest) {
2423         if (!dest) dest = quat4.create();
2424         
2425         // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
2426         // article "Quaternion Calculus and Fast Animation".
2427
2428         var fTrace = mat[0] + mat[4] + mat[8];
2429         var fRoot;
2430
2431         if ( fTrace > 0.0 ) {
2432             // |w| > 1/2, may as well choose w > 1/2
2433             fRoot = Math.sqrt(fTrace + 1.0);  // 2w
2434             dest[3] = 0.5 * fRoot;
2435             fRoot = 0.5/fRoot;  // 1/(4w)
2436             dest[0] = (mat[7]-mat[5])*fRoot;
2437             dest[1] = (mat[2]-mat[6])*fRoot;
2438             dest[2] = (mat[3]-mat[1])*fRoot;
2439         } else {
2440             // |w| <= 1/2
2441             var s_iNext = quat4.fromRotationMatrix.s_iNext = quat4.fromRotationMatrix.s_iNext || [1,2,0];
2442             var i = 0;
2443             if ( mat[4] > mat[0] )
2444               i = 1;
2445             if ( mat[8] > mat[i*3+i] )
2446               i = 2;
2447             var j = s_iNext[i];
2448             var k = s_iNext[j];
2449             
2450             fRoot = Math.sqrt(mat[i*3+i]-mat[j*3+j]-mat[k*3+k] + 1.0);
2451             dest[i] = 0.5 * fRoot;
2452             fRoot = 0.5 / fRoot;
2453             dest[3] = (mat[k*3+j] - mat[j*3+k]) * fRoot;
2454             dest[j] = (mat[j*3+i] + mat[i*3+j]) * fRoot;
2455             dest[k] = (mat[k*3+i] + mat[i*3+k]) * fRoot;
2456         }
2457         
2458         return dest;
2459     };
2460
2461     /**
2462      * Alias. See the description for quat4.fromRotationMatrix().
2463      */
2464     mat3.toQuat4 = quat4.fromRotationMatrix;
2465
2466     (function() {
2467         var mat = mat3.create();
2468         
2469         /**
2470          * Creates a quaternion from the 3 given vectors. They must be perpendicular
2471          * to one another and represent the X, Y and Z axes.
2472          *
2473          * If dest is omitted, a new quat4 will be created.
2474          *
2475          * Example: The default OpenGL orientation has a view vector [0, 0, -1],
2476          * right vector [1, 0, 0], and up vector [0, 1, 0]. A quaternion representing
2477          * this orientation could be constructed with:
2478          *
2479          *   quat = quat4.fromAxes([0, 0, -1], [1, 0, 0], [0, 1, 0], quat4.create());
2480          *
2481          * @param {vec3}  view   the view vector, or direction the object is pointing in
2482          * @param {vec3}  right  the right vector, or direction to the "right" of the object
2483          * @param {vec3}  up     the up vector, or direction towards the object's "up"
2484          * @param {quat4} [dest] an optional receiving quat4
2485          *
2486          * @returns {quat4} dest
2487          **/
2488         quat4.fromAxes = function(view, right, up, dest) {
2489             mat[0] = right[0];
2490             mat[3] = right[1];
2491             mat[6] = right[2];
2492
2493             mat[1] = up[0];
2494             mat[4] = up[1];
2495             mat[7] = up[2];
2496
2497             mat[2] = view[0];
2498             mat[5] = view[1];
2499             mat[8] = view[2];
2500
2501             return quat4.fromRotationMatrix(mat, dest);
2502         };
2503     })();
2504
2505     /**
2506      * Sets a quat4 to the Identity and returns it.
2507      *
2508      * @param {quat4} [dest] quat4 to set. If omitted, a
2509      * new quat4 will be created.
2510      *
2511      * @returns {quat4} dest
2512      */
2513     quat4.identity = function(dest) {
2514         if (!dest) dest = quat4.create();
2515         dest[0] = 0;
2516         dest[1] = 0;
2517         dest[2] = 0;
2518         dest[3] = 1;
2519         return dest;
2520     };
2521
2522     /**
2523      * Sets a quat4 from the given angle and rotation axis,
2524      * then returns it. If dest is not given, a new quat4 is created.
2525      *
2526      * @param {Number} angle  the angle in radians
2527      * @param {vec3}   axis   the axis around which to rotate
2528      * @param {quat4}  [dest] the optional quat4 to store the result
2529      *
2530      * @returns {quat4} dest
2531      **/
2532     quat4.fromAngleAxis = function(angle, axis, dest) {
2533         // The quaternion representing the rotation is
2534         //   q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)
2535         if (!dest) dest = quat4.create();
2536         
2537         var half = angle * 0.5;
2538         var s = Math.sin(half);
2539         dest[3] = Math.cos(half);
2540         dest[0] = s * axis[0];
2541         dest[1] = s * axis[1];
2542         dest[2] = s * axis[2];
2543         
2544         return dest;
2545     };
2546
2547     /**
2548      * Stores the angle and axis in a vec4, where the XYZ components represent
2549      * the axis and the W (4th) component is the angle in radians.
2550      *
2551      * If dest is not given, src will be modified in place and returned, after
2552      * which it should not be considered not a quaternion (just an axis and angle).
2553      *
2554      * @param {quat4} quat   the quaternion whose angle and axis to store
2555      * @param {vec4}  [dest] the optional vec4 to receive the data
2556      *
2557      * @returns {vec4} dest
2558      */
2559     quat4.toAngleAxis = function(src, dest) {
2560         if (!dest) dest = src;
2561         // The quaternion representing the rotation is
2562         //   q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)
2563
2564         var sqrlen = src[0]*src[0]+src[1]*src[1]+src[2]*src[2];
2565         if (sqrlen > 0)
2566         {
2567             dest[3] = 2 * Math.acos(src[3]);
2568             var invlen = glMath.invsqrt(sqrlen);
2569             dest[0] = src[0]*invlen;
2570             dest[1] = src[1]*invlen;
2571             dest[2] = src[2]*invlen;
2572         } else {
2573             // angle is 0 (mod 2*pi), so any axis will do
2574             dest[3] = 0;
2575             dest[0] = 1;
2576             dest[1] = 0;
2577             dest[2] = 0;
2578         }
2579         
2580         return dest;
2581     };
2582
2583     /**
2584      * Returns a string representation of a quaternion
2585      *
2586      * @param {quat4} quat quat4 to represent as a string
2587      *
2588      * @returns {string} String representation of quat
2589      */
2590     quat4.str = function (quat) {
2591         return '[' + quat[0] + ', ' + quat[1] + ', ' + quat[2] + ', ' + quat[3] + ']';
2592     };
2593     
2594     /**
2595      * @class 2 Dimensional Vector
2596      * @name vec2
2597      */
2598     var vec2 = {};
2599      
2600     /**
2601      * Creates a new vec2, initializing it from vec if vec
2602      * is given.
2603      *
2604      * @param {vec2} [vec] the vector's initial contents
2605      * @returns {vec2} a new 2D vector
2606      */
2607     vec2.create = function(vec) {
2608         var dest = new MatrixArray(2);
2609
2610         if (vec) {
2611             dest[0] = vec[0];
2612             dest[1] = vec[1];
2613         } else {
2614             dest[0] = 0;
2615             dest[1] = 0;
2616         }
2617         return dest;
2618     };
2619
2620     /**
2621      * Creates a new instance of a vec2, initializing it with the given arguments
2622      *
2623      * @param {number} x X value
2624      * @param {number} y Y value
2625
2626      * @returns {vec2} New vec2
2627      */
2628     vec2.createFrom = function (x, y) {
2629         var dest = new MatrixArray(2);
2630
2631         dest[0] = x;
2632         dest[1] = y;
2633
2634         return dest;
2635     };
2636     
2637     /**
2638      * Adds the vec2's together. If dest is given, the result
2639      * is stored there. Otherwise, the result is stored in vecB.
2640      *
2641      * @param {vec2} vecA the first operand
2642      * @param {vec2} vecB the second operand
2643      * @param {vec2} [dest] the optional receiving vector
2644      * @returns {vec2} dest
2645      */
2646     vec2.add = function(vecA, vecB, dest) {
2647         if (!dest) dest = vecB;
2648         dest[0] = vecA[0] + vecB[0];
2649         dest[1] = vecA[1] + vecB[1];
2650         return dest;
2651     };
2652     
2653     /**
2654      * Subtracts vecB from vecA. If dest is given, the result
2655      * is stored there. Otherwise, the result is stored in vecB.
2656      *
2657      * @param {vec2} vecA the first operand
2658      * @param {vec2} vecB the second operand
2659      * @param {vec2} [dest] the optional receiving vector
2660      * @returns {vec2} dest
2661      */
2662     vec2.subtract = function(vecA, vecB, dest) {
2663         if (!dest) dest = vecB;
2664         dest[0] = vecA[0] - vecB[0];
2665         dest[1] = vecA[1] - vecB[1];
2666         return dest;
2667     };
2668     
2669     /**
2670      * Multiplies vecA with vecB. If dest is given, the result
2671      * is stored there. Otherwise, the result is stored in vecB.
2672      *
2673      * @param {vec2} vecA the first operand
2674      * @param {vec2} vecB the second operand
2675      * @param {vec2} [dest] the optional receiving vector
2676      * @returns {vec2} dest
2677      */
2678     vec2.multiply = function(vecA, vecB, dest) {
2679         if (!dest) dest = vecB;
2680         dest[0] = vecA[0] * vecB[0];
2681         dest[1] = vecA[1] * vecB[1];
2682         return dest;
2683     };
2684     
2685     /**
2686      * Divides vecA by vecB. If dest is given, the result
2687      * is stored there. Otherwise, the result is stored in vecB.
2688      *
2689      * @param {vec2} vecA the first operand
2690      * @param {vec2} vecB the second operand
2691      * @param {vec2} [dest] the optional receiving vector
2692      * @returns {vec2} dest
2693      */
2694     vec2.divide = function(vecA, vecB, dest) {
2695         if (!dest) dest = vecB;
2696         dest[0] = vecA[0] / vecB[0];
2697         dest[1] = vecA[1] / vecB[1];
2698         return dest;
2699     };
2700     
2701     /**
2702      * Scales vecA by some scalar number. If dest is given, the result
2703      * is stored there. Otherwise, the result is stored in vecA.
2704      *
2705      * This is the same as multiplying each component of vecA
2706      * by the given scalar.
2707      *
2708      * @param {vec2}   vecA the vector to be scaled
2709      * @param {Number} scalar the amount to scale the vector by
2710      * @param {vec2}   [dest] the optional receiving vector
2711      * @returns {vec2} dest
2712      */
2713     vec2.scale = function(vecA, scalar, dest) {
2714         if (!dest) dest = vecA;
2715         dest[0] = vecA[0] * scalar;
2716         dest[1] = vecA[1] * scalar;
2717         return dest;
2718     };
2719
2720     /**
2721      * Calculates the euclidian distance between two vec2
2722      *
2723      * Params:
2724      * @param {vec2} vecA First vector
2725      * @param {vec2} vecB Second vector
2726      *
2727      * @returns {number} Distance between vecA and vecB
2728      */
2729     vec2.dist = function (vecA, vecB) {
2730         var x = vecB[0] - vecA[0],
2731             y = vecB[1] - vecA[1];
2732         return Math.sqrt(x*x + y*y);
2733     };
2734
2735     /**
2736      * Copies the values of one vec2 to another
2737      *
2738      * @param {vec2} vec vec2 containing values to copy
2739      * @param {vec2} dest vec2 receiving copied values
2740      *
2741      * @returns {vec2} dest
2742      */
2743     vec2.set = function (vec, dest) {
2744         dest[0] = vec[0];
2745         dest[1] = vec[1];
2746         return dest;
2747     };
2748
2749     /**
2750      * Compares two vectors for equality within a certain margin of error
2751      *
2752      * @param {vec2} a First vector
2753      * @param {vec2} b Second vector
2754      *
2755      * @returns {Boolean} True if a is equivalent to b
2756      */
2757     vec2.equal = function (a, b) {
2758         return a === b || (
2759             Math.abs(a[0] - b[0]) < FLOAT_EPSILON &&
2760             Math.abs(a[1] - b[1]) < FLOAT_EPSILON
2761         );
2762     };
2763
2764     /**
2765      * Negates the components of a vec2
2766      *
2767      * @param {vec2} vec vec2 to negate
2768      * @param {vec2} [dest] vec2 receiving operation result. If not specified result is written to vec
2769      *
2770      * @returns {vec2} dest if specified, vec otherwise
2771      */
2772     vec2.negate = function (vec, dest) {
2773         if (!dest) { dest = vec; }
2774         dest[0] = -vec[0];
2775         dest[1] = -vec[1];
2776         return dest;
2777     };
2778
2779     /**
2780      * Normlize a vec2
2781      *
2782      * @param {vec2} vec vec2 to normalize
2783      * @param {vec2} [dest] vec2 receiving operation result. If not specified result is written to vec
2784      *
2785      * @returns {vec2} dest if specified, vec otherwise
2786      */
2787     vec2.normalize = function (vec, dest) {
2788         if (!dest) { dest = vec; }
2789         var mag = vec[0] * vec[0] + vec[1] * vec[1];
2790         if (mag > 0) {
2791             mag = Math.sqrt(mag);
2792             dest[0] = vec[0] / mag;
2793             dest[1] = vec[1] / mag;
2794         } else {
2795             dest[0] = dest[1] = 0;
2796         }
2797         return dest;
2798     };
2799
2800     /**
2801      * Computes the cross product of two vec2's. Note that the cross product must by definition
2802      * produce a 3D vector. If a dest vector is given, it will contain the resultant 3D vector.
2803      * Otherwise, a scalar number will be returned, representing the vector's Z coordinate, since
2804      * its X and Y must always equal 0.
2805      *
2806      * Examples:
2807      *    var crossResult = vec3.create();
2808      *    vec2.cross([1, 2], [3, 4], crossResult);
2809      *    //=> [0, 0, -2]
2810      *
2811      *    vec2.cross([1, 2], [3, 4]);
2812      *    //=> -2
2813      *
2814      * See http://stackoverflow.com/questions/243945/calculating-a-2d-vectors-cross-product
2815      * for some interesting facts.
2816      *
2817      * @param {vec2} vecA left operand
2818      * @param {vec2} vecB right operand
2819      * @param {vec2} [dest] optional vec2 receiving result. If not specified a scalar is returned
2820      *
2821      */
2822     vec2.cross = function (vecA, vecB, dest) {
2823         var z = vecA[0] * vecB[1] - vecA[1] * vecB[0];
2824         if (!dest) return z;
2825         dest[0] = dest[1] = 0;
2826         dest[2] = z;
2827         return dest;
2828     };
2829     
2830     /**
2831      * Caclulates the length of a vec2
2832      *
2833      * @param {vec2} vec vec2 to calculate length of
2834      *
2835      * @returns {Number} Length of vec
2836      */
2837     vec2.length = function (vec) {
2838       var x = vec[0], y = vec[1];
2839       return Math.sqrt(x * x + y * y);
2840     };
2841
2842     /**
2843      * Caclulates the squared length of a vec2
2844      *
2845      * @param {vec2} vec vec2 to calculate squared length of
2846      *
2847      * @returns {Number} Squared Length of vec
2848      */
2849     vec2.squaredLength = function (vec) {
2850       var x = vec[0], y = vec[1];
2851       return x * x + y * y;
2852     };
2853
2854     /**
2855      * Caclulates the dot product of two vec2s
2856      *
2857      * @param {vec2} vecA First operand
2858      * @param {vec2} vecB Second operand
2859      *
2860      * @returns {Number} Dot product of vecA and vecB
2861      */
2862     vec2.dot = function (vecA, vecB) {
2863         return vecA[0] * vecB[0] + vecA[1] * vecB[1];
2864     };
2865     
2866     /**
2867      * Generates a 2D unit vector pointing from one vector to another
2868      *
2869      * @param {vec2} vecA Origin vec2
2870      * @param {vec2} vecB vec2 to point to
2871      * @param {vec2} [dest] vec2 receiving operation result. If not specified result is written to vecA
2872      *
2873      * @returns {vec2} dest if specified, vecA otherwise
2874      */
2875     vec2.direction = function (vecA, vecB, dest) {
2876         if (!dest) { dest = vecA; }
2877
2878         var x = vecA[0] - vecB[0],
2879             y = vecA[1] - vecB[1],
2880             len = x * x + y * y;
2881
2882         if (!len) {
2883             dest[0] = 0;
2884             dest[1] = 0;
2885             dest[2] = 0;
2886             return dest;
2887         }
2888
2889         len = 1 / Math.sqrt(len);
2890         dest[0] = x * len;
2891         dest[1] = y * len;
2892         return dest;
2893     };
2894
2895     /**
2896      * Performs a linear interpolation between two vec2
2897      *
2898      * @param {vec2} vecA First vector
2899      * @param {vec2} vecB Second vector
2900      * @param {Number} lerp Interpolation amount between the two inputs
2901      * @param {vec2} [dest] vec2 receiving operation result. If not specified result is written to vecA
2902      *
2903      * @returns {vec2} dest if specified, vecA otherwise
2904      */
2905     vec2.lerp = function (vecA, vecB, lerp, dest) {
2906         if (!dest) { dest = vecA; }
2907         dest[0] = vecA[0] + lerp * (vecB[0] - vecA[0]);
2908         dest[1] = vecA[1] + lerp * (vecB[1] - vecA[1]);
2909         return dest;
2910     };
2911
2912     /**
2913      * Returns a string representation of a vector
2914      *
2915      * @param {vec2} vec Vector to represent as a string
2916      *
2917      * @returns {String} String representation of vec
2918      */
2919     vec2.str = function (vec) {
2920         return '[' + vec[0] + ', ' + vec[1] + ']';
2921     };
2922     
2923     /**
2924      * @class 2x2 Matrix
2925      * @name mat2
2926      */
2927     var mat2 = {};
2928     
2929     /**
2930      * Creates a new 2x2 matrix. If src is given, the new matrix
2931      * is initialized to those values.
2932      *
2933      * @param {mat2} [src] the seed values for the new matrix, if any
2934      * @returns {mat2} a new matrix
2935      */
2936     mat2.create = function(src) {
2937         var dest = new MatrixArray(4);
2938         
2939         if (src) {
2940             dest[0] = src[0];
2941             dest[1] = src[1];
2942             dest[2] = src[2];
2943             dest[3] = src[3];
2944         } else {
2945             dest[0] = dest[1] = dest[2] = dest[3] = 0;
2946         }
2947         return dest;
2948     };
2949
2950     /**
2951      * Creates a new instance of a mat2, initializing it with the given arguments
2952      *
2953      * @param {number} m00
2954      * @param {number} m01
2955      * @param {number} m10
2956      * @param {number} m11
2957
2958      * @returns {mat2} New mat2
2959      */
2960     mat2.createFrom = function (m00, m01, m10, m11) {
2961         var dest = new MatrixArray(4);
2962
2963         dest[0] = m00;
2964         dest[1] = m01;
2965         dest[2] = m10;
2966         dest[3] = m11;
2967
2968         return dest;
2969     };
2970     
2971     /**
2972      * Copies the values of one mat2 to another
2973      *
2974      * @param {mat2} mat mat2 containing values to copy
2975      * @param {mat2} dest mat2 receiving copied values
2976      *
2977      * @returns {mat2} dest
2978      */
2979     mat2.set = function (mat, dest) {
2980         dest[0] = mat[0];
2981         dest[1] = mat[1];
2982         dest[2] = mat[2];
2983         dest[3] = mat[3];
2984         return dest;
2985     };
2986
2987     /**
2988      * Compares two matrices for equality within a certain margin of error
2989      *
2990      * @param {mat2} a First matrix
2991      * @param {mat2} b Second matrix
2992      *
2993      * @returns {Boolean} True if a is equivalent to b
2994      */
2995     mat2.equal = function (a, b) {
2996         return a === b || (
2997             Math.abs(a[0] - b[0]) < FLOAT_EPSILON &&
2998             Math.abs(a[1] - b[1]) < FLOAT_EPSILON &&
2999             Math.abs(a[2] - b[2]) < FLOAT_EPSILON &&
3000             Math.abs(a[3] - b[3]) < FLOAT_EPSILON
3001         );
3002     };
3003
3004     /**
3005      * Sets a mat2 to an identity matrix
3006      *
3007      * @param {mat2} [dest] mat2 to set. If omitted a new one will be created.
3008      *
3009      * @returns {mat2} dest
3010      */
3011     mat2.identity = function (dest) {
3012         if (!dest) { dest = mat2.create(); }
3013         dest[0] = 1;
3014         dest[1] = 0;
3015         dest[2] = 0;
3016         dest[3] = 1;
3017         return dest;
3018     };
3019
3020     /**
3021      * Transposes a mat2 (flips the values over the diagonal)
3022      *
3023      * @param {mat2} mat mat2 to transpose
3024      * @param {mat2} [dest] mat2 receiving transposed values. If not specified result is written to mat
3025      *
3026      * @param {mat2} dest if specified, mat otherwise
3027      */
3028     mat2.transpose = function (mat, dest) {
3029         // If we are transposing ourselves we can skip a few steps but have to cache some values
3030         if (!dest || mat === dest) {
3031             var a00 = mat[1];
3032             mat[1] = mat[2];
3033             mat[2] = a00;
3034             return mat;
3035         }
3036         
3037         dest[0] = mat[0];
3038         dest[1] = mat[2];
3039         dest[2] = mat[1];
3040         dest[3] = mat[3];
3041         return dest;
3042     };
3043
3044     /**
3045      * Calculates the determinant of a mat2
3046      *
3047      * @param {mat2} mat mat2 to calculate determinant of
3048      *
3049      * @returns {Number} determinant of mat
3050      */
3051     mat2.determinant = function (mat) {
3052       return mat[0] * mat[3] - mat[2] * mat[1];
3053     };
3054     
3055     /**
3056      * Calculates the inverse matrix of a mat2
3057      *
3058      * @param {mat2} mat mat2 to calculate inverse of
3059      * @param {mat2} [dest] mat2 receiving inverse matrix. If not specified result is written to mat
3060      *
3061      * @param {mat2} dest is specified, mat otherwise, null if matrix cannot be inverted
3062      */
3063     mat2.inverse = function (mat, dest) {
3064         if (!dest) { dest = mat; }
3065         var a0 = mat[0], a1 = mat[1], a2 = mat[2], a3 = mat[3];
3066         var det = a0 * a3 - a2 * a1;
3067         if (!det) return null;
3068         
3069         det = 1.0 / det;
3070         dest[0] =  a3 * det;
3071         dest[1] = -a1 * det;
3072         dest[2] = -a2 * det;
3073         dest[3] =  a0 * det;
3074         return dest;
3075     };
3076     
3077     /**
3078      * Performs a matrix multiplication
3079      *
3080      * @param {mat2} matA First operand
3081      * @param {mat2} matB Second operand
3082      * @param {mat2} [dest] mat2 receiving operation result. If not specified result is written to matA
3083      *
3084      * @returns {mat2} dest if specified, matA otherwise
3085      */
3086     mat2.multiply = function (matA, matB, dest) {
3087         if (!dest) { dest = matA; }
3088         var a11 = matA[0],
3089             a12 = matA[1],
3090             a21 = matA[2],
3091             a22 = matA[3];
3092         dest[0] = a11 * matB[0] + a12 * matB[2];
3093         dest[1] = a11 * matB[1] + a12 * matB[3];
3094         dest[2] = a21 * matB[0] + a22 * matB[2];
3095         dest[3] = a21 * matB[1] + a22 * matB[3];
3096         return dest;
3097     };
3098
3099     /**
3100      * Rotates a 2x2 matrix by an angle
3101      *
3102      * @param {mat2}   mat   The matrix to rotate
3103      * @param {Number} angle The angle in radians
3104      * @param {mat2} [dest]  Optional mat2 receiving the result. If omitted mat will be used.
3105      *
3106      * @returns {mat2} dest if specified, mat otherwise
3107      */
3108     mat2.rotate = function (mat, angle, dest) {
3109         if (!dest) { dest = mat; }
3110         var a11 = mat[0],
3111             a12 = mat[1],
3112             a21 = mat[2],
3113             a22 = mat[3],
3114             s = Math.sin(angle),
3115             c = Math.cos(angle);
3116         dest[0] = a11 *  c + a12 * s;
3117         dest[1] = a11 * -s + a12 * c;
3118         dest[2] = a21 *  c + a22 * s;
3119         dest[3] = a21 * -s + a22 * c;
3120         return dest;
3121     };
3122
3123     /**
3124      * Multiplies the vec2 by the given 2x2 matrix
3125      *
3126      * @param {mat2} matrix the 2x2 matrix to multiply against
3127      * @param {vec2} vec    the vector to multiply
3128      * @param {vec2} [dest] an optional receiving vector. If not given, vec is used.
3129      *
3130      * @returns {vec2} The multiplication result
3131      **/
3132     mat2.multiplyVec2 = function(matrix, vec, dest) {
3133       if (!dest) dest = vec;
3134       var x = vec[0], y = vec[1];
3135       dest[0] = x * matrix[0] + y * matrix[1];
3136       dest[1] = x * matrix[2] + y * matrix[3];
3137       return dest;
3138     };
3139     
3140     /**
3141      * Scales the mat2 by the dimensions in the given vec2
3142      *
3143      * @param {mat2} matrix the 2x2 matrix to scale
3144      * @param {vec2} vec    the vector containing the dimensions to scale by
3145      * @param {vec2} [dest] an optional receiving mat2. If not given, matrix is used.
3146      *
3147      * @returns {mat2} dest if specified, matrix otherwise
3148      **/
3149     mat2.scale = function(matrix, vec, dest) {
3150       if (!dest) { dest = matrix; }
3151       var a11 = matrix[0],
3152           a12 = matrix[1],
3153           a21 = matrix[2],
3154           a22 = matrix[3],
3155           b11 = vec[0],
3156           b22 = vec[1];
3157       dest[0] = a11 * b11;
3158       dest[1] = a12 * b22;
3159       dest[2] = a21 * b11;
3160       dest[3] = a22 * b22;
3161       return dest;
3162     };
3163
3164     /**
3165      * Returns a string representation of a mat2
3166      *
3167      * @param {mat2} mat mat2 to represent as a string
3168      *
3169      * @param {String} String representation of mat
3170      */
3171     mat2.str = function (mat) {
3172         return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + ', ' + mat[3] + ']';
3173     };
3174     
3175     /**
3176      * @class 4 Dimensional Vector
3177      * @name vec4
3178      */
3179     var vec4 = {};
3180      
3181     /**
3182      * Creates a new vec4, initializing it from vec if vec
3183      * is given.
3184      *
3185      * @param {vec4} [vec] the vector's initial contents
3186      * @returns {vec4} a new 2D vector
3187      */
3188     vec4.create = function(vec) {
3189         var dest = new MatrixArray(4);
3190         
3191         if (vec) {
3192             dest[0] = vec[0];
3193             dest[1] = vec[1];
3194             dest[2] = vec[2];
3195             dest[3] = vec[3];
3196         } else {
3197             dest[0] = 0;
3198             dest[1] = 0;
3199             dest[2] = 0;
3200             dest[3] = 0;
3201         }
3202         return dest;
3203     };
3204
3205     /**
3206      * Creates a new instance of a vec4, initializing it with the given arguments
3207      *
3208      * @param {number} x X value
3209      * @param {number} y Y value
3210      * @param {number} z Z value
3211      * @param {number} w W value
3212
3213      * @returns {vec4} New vec4
3214      */
3215     vec4.createFrom = function (x, y, z, w) {
3216         var dest = new MatrixArray(4);
3217
3218         dest[0] = x;
3219         dest[1] = y;
3220         dest[2] = z;
3221         dest[3] = w;
3222
3223         return dest;
3224     };
3225     
3226     /**
3227      * Adds the vec4's together. If dest is given, the result
3228      * is stored there. Otherwise, the result is stored in vecB.
3229      *
3230      * @param {vec4} vecA the first operand
3231      * @param {vec4} vecB the second operand
3232      * @param {vec4} [dest] the optional receiving vector
3233      * @returns {vec4} dest
3234      */
3235     vec4.add = function(vecA, vecB, dest) {
3236       if (!dest) dest = vecB;
3237       dest[0] = vecA[0] + vecB[0];
3238       dest[1] = vecA[1] + vecB[1];
3239       dest[2] = vecA[2] + vecB[2];
3240       dest[3] = vecA[3] + vecB[3];
3241       return dest;
3242     };
3243     
3244     /**
3245      * Subtracts vecB from vecA. If dest is given, the result
3246      * is stored there. Otherwise, the result is stored in vecB.
3247      *
3248      * @param {vec4} vecA the first operand
3249      * @param {vec4} vecB the second operand
3250      * @param {vec4} [dest] the optional receiving vector
3251      * @returns {vec4} dest
3252      */
3253     vec4.subtract = function(vecA, vecB, dest) {
3254       if (!dest) dest = vecB;
3255       dest[0] = vecA[0] - vecB[0];
3256       dest[1] = vecA[1] - vecB[1];
3257       dest[2] = vecA[2] - vecB[2];
3258       dest[3] = vecA[3] - vecB[3];
3259       return dest;
3260     };
3261     
3262     /**
3263      * Multiplies vecA with vecB. If dest is given, the result
3264      * is stored there. Otherwise, the result is stored in vecB.
3265      *
3266      * @param {vec4} vecA the first operand
3267      * @param {vec4} vecB the second operand
3268      * @param {vec4} [dest] the optional receiving vector
3269      * @returns {vec4} dest
3270      */
3271     vec4.multiply = function(vecA, vecB, dest) {
3272       if (!dest) dest = vecB;
3273       dest[0] = vecA[0] * vecB[0];
3274       dest[1] = vecA[1] * vecB[1];
3275       dest[2] = vecA[2] * vecB[2];
3276       dest[3] = vecA[3] * vecB[3];
3277       return dest;
3278     };
3279     
3280     /**
3281      * Divides vecA by vecB. If dest is given, the result
3282      * is stored there. Otherwise, the result is stored in vecB.
3283      *
3284      * @param {vec4} vecA the first operand
3285      * @param {vec4} vecB the second operand
3286      * @param {vec4} [dest] the optional receiving vector
3287      * @returns {vec4} dest
3288      */
3289     vec4.divide = function(vecA, vecB, dest) {
3290       if (!dest) dest = vecB;
3291       dest[0] = vecA[0] / vecB[0];
3292       dest[1] = vecA[1] / vecB[1];
3293       dest[2] = vecA[2] / vecB[2];
3294       dest[3] = vecA[3] / vecB[3];
3295       return dest;
3296     };
3297     
3298     /**
3299      * Scales vecA by some scalar number. If dest is given, the result
3300      * is stored there. Otherwise, the result is stored in vecA.
3301      *
3302      * This is the same as multiplying each component of vecA
3303      * by the given scalar.
3304      *
3305      * @param {vec4}   vecA the vector to be scaled
3306      * @param {Number} scalar the amount to scale the vector by
3307      * @param {vec4}   [dest] the optional receiving vector
3308      * @returns {vec4} dest
3309      */
3310     vec4.scale = function(vecA, scalar, dest) {
3311       if (!dest) dest = vecA;
3312       dest[0] = vecA[0] * scalar;
3313       dest[1] = vecA[1] * scalar;
3314       dest[2] = vecA[2] * scalar;
3315       dest[3] = vecA[3] * scalar;
3316       return dest;
3317     };
3318
3319     /**
3320      * Copies the values of one vec4 to another
3321      *
3322      * @param {vec4} vec vec4 containing values to copy
3323      * @param {vec4} dest vec4 receiving copied values
3324      *
3325      * @returns {vec4} dest
3326      */
3327     vec4.set = function (vec, dest) {
3328         dest[0] = vec[0];
3329         dest[1] = vec[1];
3330         dest[2] = vec[2];
3331         dest[3] = vec[3];
3332         return dest;
3333     };
3334
3335     /**
3336      * Compares two vectors for equality within a certain margin of error
3337      *
3338      * @param {vec4} a First vector
3339      * @param {vec4} b Second vector
3340      *
3341      * @returns {Boolean} True if a is equivalent to b
3342      */
3343     vec4.equal = function (a, b) {
3344         return a === b || (
3345             Math.abs(a[0] - b[0]) < FLOAT_EPSILON &&
3346             Math.abs(a[1] - b[1]) < FLOAT_EPSILON &&
3347             Math.abs(a[2] - b[2]) < FLOAT_EPSILON &&
3348             Math.abs(a[3] - b[3]) < FLOAT_EPSILON
3349         );
3350     };
3351
3352     /**
3353      * Negates the components of a vec4
3354      *
3355      * @param {vec4} vec vec4 to negate
3356      * @param {vec4} [dest] vec4 receiving operation result. If not specified result is written to vec
3357      *
3358      * @returns {vec4} dest if specified, vec otherwise
3359      */
3360     vec4.negate = function (vec, dest) {
3361         if (!dest) { dest = vec; }
3362         dest[0] = -vec[0];
3363         dest[1] = -vec[1];
3364         dest[2] = -vec[2];
3365         dest[3] = -vec[3];
3366         return dest;
3367     };
3368
3369     /**
3370      * Caclulates the length of a vec2
3371      *
3372      * @param {vec2} vec vec2 to calculate length of
3373      *
3374      * @returns {Number} Length of vec
3375      */
3376     vec4.length = function (vec) {
3377       var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
3378       return Math.sqrt(x * x + y * y + z * z + w * w);
3379     };
3380
3381     /**
3382      * Caclulates the squared length of a vec4
3383      *
3384      * @param {vec4} vec vec4 to calculate squared length of
3385      *
3386      * @returns {Number} Squared Length of vec
3387      */
3388     vec4.squaredLength = function (vec) {
3389       var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
3390       return x * x + y * y + z * z + w * w;
3391     };
3392
3393     /**
3394      * Performs a linear interpolation between two vec4
3395      *
3396      * @param {vec4} vecA First vector
3397      * @param {vec4} vecB Second vector
3398      * @param {Number} lerp Interpolation amount between the two inputs
3399      * @param {vec4} [dest] vec4 receiving operation result. If not specified result is written to vecA
3400      *
3401      * @returns {vec4} dest if specified, vecA otherwise
3402      */
3403     vec4.lerp = function (vecA, vecB, lerp, dest) {
3404         if (!dest) { dest = vecA; }
3405         dest[0] = vecA[0] + lerp * (vecB[0] - vecA[0]);
3406         dest[1] = vecA[1] + lerp * (vecB[1] - vecA[1]);
3407         dest[2] = vecA[2] + lerp * (vecB[2] - vecA[2]);
3408         dest[3] = vecA[3] + lerp * (vecB[3] - vecA[3]);
3409         return dest;
3410     };
3411
3412     /**
3413      * Returns a string representation of a vector
3414      *
3415      * @param {vec4} vec Vector to represent as a string
3416      *
3417      * @returns {String} String representation of vec
3418      */
3419     vec4.str = function (vec) {
3420         return '[' + vec[0] + ', ' + vec[1] + ', ' + vec[2] + ', ' + vec[3] + ']';
3421     };
3422
3423     /*
3424      * Exports
3425      */
3426
3427     if(root) {
3428         root.glMatrixArrayType = MatrixArray;
3429         root.MatrixArray = MatrixArray;
3430         root.setMatrixArrayType = setMatrixArrayType;
3431         root.determineMatrixArrayType = determineMatrixArrayType;
3432         root.glMath = glMath;
3433         root.vec2 = vec2;
3434         root.vec3 = vec3;
3435         root.vec4 = vec4;
3436         root.mat2 = mat2;
3437         root.mat3 = mat3;
3438         root.mat4 = mat4;
3439         root.quat4 = quat4;
3440     }
3441
3442     return {
3443         glMatrixArrayType: MatrixArray,
3444         MatrixArray: MatrixArray,
3445         setMatrixArrayType: setMatrixArrayType,
3446         determineMatrixArrayType: determineMatrixArrayType,
3447         glMath: glMath,
3448         vec2: vec2,
3449         vec3: vec3,
3450         vec4: vec4,
3451         mat2: mat2,
3452         mat3: mat3,
3453         mat4: mat4,
3454         quat4: quat4
3455     };
3456 }));