Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / third_party / tvcm / third_party / gl-matrix / src / gl-matrix / mat4.js
1 /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
2
3 Redistribution and use in source and binary forms, with or without modification,
4 are permitted provided that the following conditions are met:
5
6   * Redistributions of source code must retain the above copyright notice, this
7     list of conditions and the following disclaimer.
8   * Redistributions in binary form must reproduce the above copyright notice,
9     this list of conditions and the following disclaimer in the documentation 
10     and/or other materials provided with the distribution.
11
12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
15 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
16 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
23 /**
24  * @class 4x4 Matrix
25  * @name mat4
26  */
27 var mat4 = {};
28
29 /**
30  * Creates a new identity mat4
31  *
32  * @returns {mat4} a new 4x4 matrix
33  */
34 mat4.create = function() {
35     var out = new GLMAT_ARRAY_TYPE(16);
36     out[0] = 1;
37     out[1] = 0;
38     out[2] = 0;
39     out[3] = 0;
40     out[4] = 0;
41     out[5] = 1;
42     out[6] = 0;
43     out[7] = 0;
44     out[8] = 0;
45     out[9] = 0;
46     out[10] = 1;
47     out[11] = 0;
48     out[12] = 0;
49     out[13] = 0;
50     out[14] = 0;
51     out[15] = 1;
52     return out;
53 };
54
55 /**
56  * Creates a new mat4 initialized with values from an existing matrix
57  *
58  * @param {mat4} a matrix to clone
59  * @returns {mat4} a new 4x4 matrix
60  */
61 mat4.clone = function(a) {
62     var out = new GLMAT_ARRAY_TYPE(16);
63     out[0] = a[0];
64     out[1] = a[1];
65     out[2] = a[2];
66     out[3] = a[3];
67     out[4] = a[4];
68     out[5] = a[5];
69     out[6] = a[6];
70     out[7] = a[7];
71     out[8] = a[8];
72     out[9] = a[9];
73     out[10] = a[10];
74     out[11] = a[11];
75     out[12] = a[12];
76     out[13] = a[13];
77     out[14] = a[14];
78     out[15] = a[15];
79     return out;
80 };
81
82 /**
83  * Copy the values from one mat4 to another
84  *
85  * @param {mat4} out the receiving matrix
86  * @param {mat4} a the source matrix
87  * @returns {mat4} out
88  */
89 mat4.copy = function(out, a) {
90     out[0] = a[0];
91     out[1] = a[1];
92     out[2] = a[2];
93     out[3] = a[3];
94     out[4] = a[4];
95     out[5] = a[5];
96     out[6] = a[6];
97     out[7] = a[7];
98     out[8] = a[8];
99     out[9] = a[9];
100     out[10] = a[10];
101     out[11] = a[11];
102     out[12] = a[12];
103     out[13] = a[13];
104     out[14] = a[14];
105     out[15] = a[15];
106     return out;
107 };
108
109 /**
110  * Set a mat4 to the identity matrix
111  *
112  * @param {mat4} out the receiving matrix
113  * @returns {mat4} out
114  */
115 mat4.identity = function(out) {
116     out[0] = 1;
117     out[1] = 0;
118     out[2] = 0;
119     out[3] = 0;
120     out[4] = 0;
121     out[5] = 1;
122     out[6] = 0;
123     out[7] = 0;
124     out[8] = 0;
125     out[9] = 0;
126     out[10] = 1;
127     out[11] = 0;
128     out[12] = 0;
129     out[13] = 0;
130     out[14] = 0;
131     out[15] = 1;
132     return out;
133 };
134
135 /**
136  * Transpose the values of a mat4
137  *
138  * @param {mat4} out the receiving matrix
139  * @param {mat4} a the source matrix
140  * @returns {mat4} out
141  */
142 mat4.transpose = function(out, a) {
143     // If we are transposing ourselves we can skip a few steps but have to cache some values
144     if (out === a) {
145         var a01 = a[1], a02 = a[2], a03 = a[3],
146             a12 = a[6], a13 = a[7],
147             a23 = a[11];
148
149         out[1] = a[4];
150         out[2] = a[8];
151         out[3] = a[12];
152         out[4] = a01;
153         out[6] = a[9];
154         out[7] = a[13];
155         out[8] = a02;
156         out[9] = a12;
157         out[11] = a[14];
158         out[12] = a03;
159         out[13] = a13;
160         out[14] = a23;
161     } else {
162         out[0] = a[0];
163         out[1] = a[4];
164         out[2] = a[8];
165         out[3] = a[12];
166         out[4] = a[1];
167         out[5] = a[5];
168         out[6] = a[9];
169         out[7] = a[13];
170         out[8] = a[2];
171         out[9] = a[6];
172         out[10] = a[10];
173         out[11] = a[14];
174         out[12] = a[3];
175         out[13] = a[7];
176         out[14] = a[11];
177         out[15] = a[15];
178     }
179     
180     return out;
181 };
182
183 /**
184  * Inverts a mat4
185  *
186  * @param {mat4} out the receiving matrix
187  * @param {mat4} a the source matrix
188  * @returns {mat4} out
189  */
190 mat4.invert = function(out, a) {
191     var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
192         a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
193         a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
194         a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
195
196         b00 = a00 * a11 - a01 * a10,
197         b01 = a00 * a12 - a02 * a10,
198         b02 = a00 * a13 - a03 * a10,
199         b03 = a01 * a12 - a02 * a11,
200         b04 = a01 * a13 - a03 * a11,
201         b05 = a02 * a13 - a03 * a12,
202         b06 = a20 * a31 - a21 * a30,
203         b07 = a20 * a32 - a22 * a30,
204         b08 = a20 * a33 - a23 * a30,
205         b09 = a21 * a32 - a22 * a31,
206         b10 = a21 * a33 - a23 * a31,
207         b11 = a22 * a33 - a23 * a32,
208
209         // Calculate the determinant
210         det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
211
212     if (!det) { 
213         return null; 
214     }
215     det = 1.0 / det;
216
217     out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
218     out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
219     out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
220     out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
221     out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
222     out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
223     out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
224     out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
225     out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
226     out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
227     out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
228     out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
229     out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
230     out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
231     out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
232     out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
233
234     return out;
235 };
236
237 /**
238  * Calculates the adjugate of a mat4
239  *
240  * @param {mat4} out the receiving matrix
241  * @param {mat4} a the source matrix
242  * @returns {mat4} out
243  */
244 mat4.adjoint = function(out, a) {
245     var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
246         a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
247         a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
248         a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
249
250     out[0]  =  (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
251     out[1]  = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
252     out[2]  =  (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
253     out[3]  = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
254     out[4]  = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
255     out[5]  =  (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
256     out[6]  = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
257     out[7]  =  (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
258     out[8]  =  (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
259     out[9]  = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
260     out[10] =  (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
261     out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
262     out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
263     out[13] =  (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
264     out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
265     out[15] =  (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
266     return out;
267 };
268
269 /**
270  * Calculates the determinant of a mat4
271  *
272  * @param {mat4} a the source matrix
273  * @returns {Number} determinant of a
274  */
275 mat4.determinant = function (a) {
276     var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
277         a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
278         a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
279         a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
280
281         b00 = a00 * a11 - a01 * a10,
282         b01 = a00 * a12 - a02 * a10,
283         b02 = a00 * a13 - a03 * a10,
284         b03 = a01 * a12 - a02 * a11,
285         b04 = a01 * a13 - a03 * a11,
286         b05 = a02 * a13 - a03 * a12,
287         b06 = a20 * a31 - a21 * a30,
288         b07 = a20 * a32 - a22 * a30,
289         b08 = a20 * a33 - a23 * a30,
290         b09 = a21 * a32 - a22 * a31,
291         b10 = a21 * a33 - a23 * a31,
292         b11 = a22 * a33 - a23 * a32;
293
294     // Calculate the determinant
295     return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
296 };
297
298 /**
299  * Multiplies two mat4's
300  *
301  * @param {mat4} out the receiving matrix
302  * @param {mat4} a the first operand
303  * @param {mat4} b the second operand
304  * @returns {mat4} out
305  */
306 mat4.multiply = function (out, a, b) {
307     var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
308         a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
309         a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
310         a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
311
312     // Cache only the current line of the second matrix
313     var b0  = b[0], b1 = b[1], b2 = b[2], b3 = b[3];  
314     out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
315     out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
316     out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
317     out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
318
319     b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
320     out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
321     out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
322     out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
323     out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
324
325     b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
326     out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
327     out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
328     out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
329     out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
330
331     b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
332     out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
333     out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
334     out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
335     out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
336     return out;
337 };
338
339 /**
340  * Alias for {@link mat4.multiply}
341  * @function
342  */
343 mat4.mul = mat4.multiply;
344
345 /**
346  * Translate a mat4 by the given vector
347  *
348  * @param {mat4} out the receiving matrix
349  * @param {mat4} a the matrix to translate
350  * @param {vec3} v vector to translate by
351  * @returns {mat4} out
352  */
353 mat4.translate = function (out, a, v) {
354     var x = v[0], y = v[1], z = v[2],
355         a00, a01, a02, a03,
356         a10, a11, a12, a13,
357         a20, a21, a22, a23;
358
359     if (a === out) {
360         out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
361         out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
362         out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
363         out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
364     } else {
365         a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
366         a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
367         a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
368
369         out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
370         out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
371         out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
372
373         out[12] = a00 * x + a10 * y + a20 * z + a[12];
374         out[13] = a01 * x + a11 * y + a21 * z + a[13];
375         out[14] = a02 * x + a12 * y + a22 * z + a[14];
376         out[15] = a03 * x + a13 * y + a23 * z + a[15];
377     }
378
379     return out;
380 };
381
382 /**
383  * Scales the mat4 by the dimensions in the given vec3
384  *
385  * @param {mat4} out the receiving matrix
386  * @param {mat4} a the matrix to scale
387  * @param {vec3} v the vec3 to scale the matrix by
388  * @returns {mat4} out
389  **/
390 mat4.scale = function(out, a, v) {
391     var x = v[0], y = v[1], z = v[2];
392
393     out[0] = a[0] * x;
394     out[1] = a[1] * x;
395     out[2] = a[2] * x;
396     out[3] = a[3] * x;
397     out[4] = a[4] * y;
398     out[5] = a[5] * y;
399     out[6] = a[6] * y;
400     out[7] = a[7] * y;
401     out[8] = a[8] * z;
402     out[9] = a[9] * z;
403     out[10] = a[10] * z;
404     out[11] = a[11] * z;
405     out[12] = a[12];
406     out[13] = a[13];
407     out[14] = a[14];
408     out[15] = a[15];
409     return out;
410 };
411
412 /**
413  * Rotates a mat4 by the given angle
414  *
415  * @param {mat4} out the receiving matrix
416  * @param {mat4} a the matrix to rotate
417  * @param {Number} rad the angle to rotate the matrix by
418  * @param {vec3} axis the axis to rotate around
419  * @returns {mat4} out
420  */
421 mat4.rotate = function (out, a, rad, axis) {
422     var x = axis[0], y = axis[1], z = axis[2],
423         len = Math.sqrt(x * x + y * y + z * z),
424         s, c, t,
425         a00, a01, a02, a03,
426         a10, a11, a12, a13,
427         a20, a21, a22, a23,
428         b00, b01, b02,
429         b10, b11, b12,
430         b20, b21, b22;
431
432     if (Math.abs(len) < GLMAT_EPSILON) { return null; }
433     
434     len = 1 / len;
435     x *= len;
436     y *= len;
437     z *= len;
438
439     s = Math.sin(rad);
440     c = Math.cos(rad);
441     t = 1 - c;
442
443     a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
444     a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
445     a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
446
447     // Construct the elements of the rotation matrix
448     b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
449     b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
450     b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
451
452     // Perform rotation-specific matrix multiplication
453     out[0] = a00 * b00 + a10 * b01 + a20 * b02;
454     out[1] = a01 * b00 + a11 * b01 + a21 * b02;
455     out[2] = a02 * b00 + a12 * b01 + a22 * b02;
456     out[3] = a03 * b00 + a13 * b01 + a23 * b02;
457     out[4] = a00 * b10 + a10 * b11 + a20 * b12;
458     out[5] = a01 * b10 + a11 * b11 + a21 * b12;
459     out[6] = a02 * b10 + a12 * b11 + a22 * b12;
460     out[7] = a03 * b10 + a13 * b11 + a23 * b12;
461     out[8] = a00 * b20 + a10 * b21 + a20 * b22;
462     out[9] = a01 * b20 + a11 * b21 + a21 * b22;
463     out[10] = a02 * b20 + a12 * b21 + a22 * b22;
464     out[11] = a03 * b20 + a13 * b21 + a23 * b22;
465
466     if (a !== out) { // If the source and destination differ, copy the unchanged last row
467         out[12] = a[12];
468         out[13] = a[13];
469         out[14] = a[14];
470         out[15] = a[15];
471     }
472     return out;
473 };
474
475 /**
476  * Rotates a matrix by the given angle around the X axis
477  *
478  * @param {mat4} out the receiving matrix
479  * @param {mat4} a the matrix to rotate
480  * @param {Number} rad the angle to rotate the matrix by
481  * @returns {mat4} out
482  */
483 mat4.rotateX = function (out, a, rad) {
484     var s = Math.sin(rad),
485         c = Math.cos(rad),
486         a10 = a[4],
487         a11 = a[5],
488         a12 = a[6],
489         a13 = a[7],
490         a20 = a[8],
491         a21 = a[9],
492         a22 = a[10],
493         a23 = a[11];
494
495     if (a !== out) { // If the source and destination differ, copy the unchanged rows
496         out[0]  = a[0];
497         out[1]  = a[1];
498         out[2]  = a[2];
499         out[3]  = a[3];
500         out[12] = a[12];
501         out[13] = a[13];
502         out[14] = a[14];
503         out[15] = a[15];
504     }
505
506     // Perform axis-specific matrix multiplication
507     out[4] = a10 * c + a20 * s;
508     out[5] = a11 * c + a21 * s;
509     out[6] = a12 * c + a22 * s;
510     out[7] = a13 * c + a23 * s;
511     out[8] = a20 * c - a10 * s;
512     out[9] = a21 * c - a11 * s;
513     out[10] = a22 * c - a12 * s;
514     out[11] = a23 * c - a13 * s;
515     return out;
516 };
517
518 /**
519  * Rotates a matrix by the given angle around the Y axis
520  *
521  * @param {mat4} out the receiving matrix
522  * @param {mat4} a the matrix to rotate
523  * @param {Number} rad the angle to rotate the matrix by
524  * @returns {mat4} out
525  */
526 mat4.rotateY = function (out, a, rad) {
527     var s = Math.sin(rad),
528         c = Math.cos(rad),
529         a00 = a[0],
530         a01 = a[1],
531         a02 = a[2],
532         a03 = a[3],
533         a20 = a[8],
534         a21 = a[9],
535         a22 = a[10],
536         a23 = a[11];
537
538     if (a !== out) { // If the source and destination differ, copy the unchanged rows
539         out[4]  = a[4];
540         out[5]  = a[5];
541         out[6]  = a[6];
542         out[7]  = a[7];
543         out[12] = a[12];
544         out[13] = a[13];
545         out[14] = a[14];
546         out[15] = a[15];
547     }
548
549     // Perform axis-specific matrix multiplication
550     out[0] = a00 * c - a20 * s;
551     out[1] = a01 * c - a21 * s;
552     out[2] = a02 * c - a22 * s;
553     out[3] = a03 * c - a23 * s;
554     out[8] = a00 * s + a20 * c;
555     out[9] = a01 * s + a21 * c;
556     out[10] = a02 * s + a22 * c;
557     out[11] = a03 * s + a23 * c;
558     return out;
559 };
560
561 /**
562  * Rotates a matrix by the given angle around the Z axis
563  *
564  * @param {mat4} out the receiving matrix
565  * @param {mat4} a the matrix to rotate
566  * @param {Number} rad the angle to rotate the matrix by
567  * @returns {mat4} out
568  */
569 mat4.rotateZ = function (out, a, rad) {
570     var s = Math.sin(rad),
571         c = Math.cos(rad),
572         a00 = a[0],
573         a01 = a[1],
574         a02 = a[2],
575         a03 = a[3],
576         a10 = a[4],
577         a11 = a[5],
578         a12 = a[6],
579         a13 = a[7];
580
581     if (a !== out) { // If the source and destination differ, copy the unchanged last row
582         out[8]  = a[8];
583         out[9]  = a[9];
584         out[10] = a[10];
585         out[11] = a[11];
586         out[12] = a[12];
587         out[13] = a[13];
588         out[14] = a[14];
589         out[15] = a[15];
590     }
591
592     // Perform axis-specific matrix multiplication
593     out[0] = a00 * c + a10 * s;
594     out[1] = a01 * c + a11 * s;
595     out[2] = a02 * c + a12 * s;
596     out[3] = a03 * c + a13 * s;
597     out[4] = a10 * c - a00 * s;
598     out[5] = a11 * c - a01 * s;
599     out[6] = a12 * c - a02 * s;
600     out[7] = a13 * c - a03 * s;
601     return out;
602 };
603
604 /**
605  * Creates a matrix from a quaternion rotation and vector translation
606  * This is equivalent to (but much faster than):
607  *
608  *     mat4.identity(dest);
609  *     mat4.translate(dest, vec);
610  *     var quatMat = mat4.create();
611  *     quat4.toMat4(quat, quatMat);
612  *     mat4.multiply(dest, quatMat);
613  *
614  * @param {mat4} out mat4 receiving operation result
615  * @param {quat4} q Rotation quaternion
616  * @param {vec3} v Translation vector
617  * @returns {mat4} out
618  */
619 mat4.fromRotationTranslation = function (out, q, v) {
620     // Quaternion math
621     var x = q[0], y = q[1], z = q[2], w = q[3],
622         x2 = x + x,
623         y2 = y + y,
624         z2 = z + z,
625
626         xx = x * x2,
627         xy = x * y2,
628         xz = x * z2,
629         yy = y * y2,
630         yz = y * z2,
631         zz = z * z2,
632         wx = w * x2,
633         wy = w * y2,
634         wz = w * z2;
635
636     out[0] = 1 - (yy + zz);
637     out[1] = xy + wz;
638     out[2] = xz - wy;
639     out[3] = 0;
640     out[4] = xy - wz;
641     out[5] = 1 - (xx + zz);
642     out[6] = yz + wx;
643     out[7] = 0;
644     out[8] = xz + wy;
645     out[9] = yz - wx;
646     out[10] = 1 - (xx + yy);
647     out[11] = 0;
648     out[12] = v[0];
649     out[13] = v[1];
650     out[14] = v[2];
651     out[15] = 1;
652     
653     return out;
654 };
655
656 /**
657 * Calculates a 4x4 matrix from the given quaternion
658 *
659 * @param {mat4} out mat4 receiving operation result
660 * @param {quat} q Quaternion to create matrix from
661 *
662 * @returns {mat4} out
663 */
664 mat4.fromQuat = function (out, q) {
665     var x = q[0], y = q[1], z = q[2], w = q[3],
666         x2 = x + x,
667         y2 = y + y,
668         z2 = z + z,
669
670         xx = x * x2,
671         xy = x * y2,
672         xz = x * z2,
673         yy = y * y2,
674         yz = y * z2,
675         zz = z * z2,
676         wx = w * x2,
677         wy = w * y2,
678         wz = w * z2;
679
680     out[0] = 1 - (yy + zz);
681     out[1] = xy + wz;
682     out[2] = xz - wy;
683     out[3] = 0;
684
685     out[4] = xy - wz;
686     out[5] = 1 - (xx + zz);
687     out[6] = yz + wx;
688     out[7] = 0;
689
690     out[8] = xz + wy;
691     out[9] = yz - wx;
692     out[10] = 1 - (xx + yy);
693     out[11] = 0;
694
695     out[12] = 0;
696     out[13] = 0;
697     out[14] = 0;
698     out[15] = 1;
699
700     return out;
701 };
702
703 /**
704  * Generates a frustum matrix with the given bounds
705  *
706  * @param {mat4} out mat4 frustum matrix will be written into
707  * @param {Number} left Left bound of the frustum
708  * @param {Number} right Right bound of the frustum
709  * @param {Number} bottom Bottom bound of the frustum
710  * @param {Number} top Top bound of the frustum
711  * @param {Number} near Near bound of the frustum
712  * @param {Number} far Far bound of the frustum
713  * @returns {mat4} out
714  */
715 mat4.frustum = function (out, left, right, bottom, top, near, far) {
716     var rl = 1 / (right - left),
717         tb = 1 / (top - bottom),
718         nf = 1 / (near - far);
719     out[0] = (near * 2) * rl;
720     out[1] = 0;
721     out[2] = 0;
722     out[3] = 0;
723     out[4] = 0;
724     out[5] = (near * 2) * tb;
725     out[6] = 0;
726     out[7] = 0;
727     out[8] = (right + left) * rl;
728     out[9] = (top + bottom) * tb;
729     out[10] = (far + near) * nf;
730     out[11] = -1;
731     out[12] = 0;
732     out[13] = 0;
733     out[14] = (far * near * 2) * nf;
734     out[15] = 0;
735     return out;
736 };
737
738 /**
739  * Generates a perspective projection matrix with the given bounds
740  *
741  * @param {mat4} out mat4 frustum matrix will be written into
742  * @param {number} fovy Vertical field of view in radians
743  * @param {number} aspect Aspect ratio. typically viewport width/height
744  * @param {number} near Near bound of the frustum
745  * @param {number} far Far bound of the frustum
746  * @returns {mat4} out
747  */
748 mat4.perspective = function (out, fovy, aspect, near, far) {
749     var f = 1.0 / Math.tan(fovy / 2),
750         nf = 1 / (near - far);
751     out[0] = f / aspect;
752     out[1] = 0;
753     out[2] = 0;
754     out[3] = 0;
755     out[4] = 0;
756     out[5] = f;
757     out[6] = 0;
758     out[7] = 0;
759     out[8] = 0;
760     out[9] = 0;
761     out[10] = (far + near) * nf;
762     out[11] = -1;
763     out[12] = 0;
764     out[13] = 0;
765     out[14] = (2 * far * near) * nf;
766     out[15] = 0;
767     return out;
768 };
769
770 /**
771  * Generates a orthogonal projection matrix with the given bounds
772  *
773  * @param {mat4} out mat4 frustum matrix will be written into
774  * @param {number} left Left bound of the frustum
775  * @param {number} right Right bound of the frustum
776  * @param {number} bottom Bottom bound of the frustum
777  * @param {number} top Top bound of the frustum
778  * @param {number} near Near bound of the frustum
779  * @param {number} far Far bound of the frustum
780  * @returns {mat4} out
781  */
782 mat4.ortho = function (out, left, right, bottom, top, near, far) {
783     var lr = 1 / (left - right),
784         bt = 1 / (bottom - top),
785         nf = 1 / (near - far);
786     out[0] = -2 * lr;
787     out[1] = 0;
788     out[2] = 0;
789     out[3] = 0;
790     out[4] = 0;
791     out[5] = -2 * bt;
792     out[6] = 0;
793     out[7] = 0;
794     out[8] = 0;
795     out[9] = 0;
796     out[10] = 2 * nf;
797     out[11] = 0;
798     out[12] = (left + right) * lr;
799     out[13] = (top + bottom) * bt;
800     out[14] = (far + near) * nf;
801     out[15] = 1;
802     return out;
803 };
804
805 /**
806  * Generates a look-at matrix with the given eye position, focal point, and up axis
807  *
808  * @param {mat4} out mat4 frustum matrix will be written into
809  * @param {vec3} eye Position of the viewer
810  * @param {vec3} center Point the viewer is looking at
811  * @param {vec3} up vec3 pointing up
812  * @returns {mat4} out
813  */
814 mat4.lookAt = function (out, eye, center, up) {
815     var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
816         eyex = eye[0],
817         eyey = eye[1],
818         eyez = eye[2],
819         upx = up[0],
820         upy = up[1],
821         upz = up[2],
822         centerx = center[0],
823         centery = center[1],
824         centerz = center[2];
825
826     if (Math.abs(eyex - centerx) < GLMAT_EPSILON &&
827         Math.abs(eyey - centery) < GLMAT_EPSILON &&
828         Math.abs(eyez - centerz) < GLMAT_EPSILON) {
829         return mat4.identity(out);
830     }
831
832     z0 = eyex - centerx;
833     z1 = eyey - centery;
834     z2 = eyez - centerz;
835
836     len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
837     z0 *= len;
838     z1 *= len;
839     z2 *= len;
840
841     x0 = upy * z2 - upz * z1;
842     x1 = upz * z0 - upx * z2;
843     x2 = upx * z1 - upy * z0;
844     len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
845     if (!len) {
846         x0 = 0;
847         x1 = 0;
848         x2 = 0;
849     } else {
850         len = 1 / len;
851         x0 *= len;
852         x1 *= len;
853         x2 *= len;
854     }
855
856     y0 = z1 * x2 - z2 * x1;
857     y1 = z2 * x0 - z0 * x2;
858     y2 = z0 * x1 - z1 * x0;
859
860     len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
861     if (!len) {
862         y0 = 0;
863         y1 = 0;
864         y2 = 0;
865     } else {
866         len = 1 / len;
867         y0 *= len;
868         y1 *= len;
869         y2 *= len;
870     }
871
872     out[0] = x0;
873     out[1] = y0;
874     out[2] = z0;
875     out[3] = 0;
876     out[4] = x1;
877     out[5] = y1;
878     out[6] = z1;
879     out[7] = 0;
880     out[8] = x2;
881     out[9] = y2;
882     out[10] = z2;
883     out[11] = 0;
884     out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
885     out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
886     out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
887     out[15] = 1;
888
889     return out;
890 };
891
892 /**
893  * Returns a string representation of a mat4
894  *
895  * @param {mat4} mat matrix to represent as a string
896  * @returns {String} string representation of the matrix
897  */
898 mat4.str = function (a) {
899     return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
900                     a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
901                     a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' + 
902                     a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
903 };
904
905 if(typeof(exports) !== 'undefined') {
906     exports.mat4 = mat4;
907 }