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