1/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
2
3Permission is hereby granted, free of charge, to any person obtaining a copy
4of this software and associated documentation files (the "Software"), to deal
5in the Software without restriction, including without limitation the rights
6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7copies of the Software, and to permit persons to whom the Software is
8furnished to do so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in
11all copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19THE SOFTWARE. */
20
21var glMatrix = require("./common.js");
22
23/**
24 * @class 3x3 Matrix
25 * @name mat3
26 */
27var mat3 = {};
28
29/**
30 * Creates a new identity mat3
31 *
32 * @returns {mat3} a new 3x3 matrix
33 */
34mat3.create = function() {
35    var out = new glMatrix.ARRAY_TYPE(9);
36    out[0] = 1;
37    out[1] = 0;
38    out[2] = 0;
39    out[3] = 0;
40    out[4] = 1;
41    out[5] = 0;
42    out[6] = 0;
43    out[7] = 0;
44    out[8] = 1;
45    return out;
46};
47
48/**
49 * Copies the upper-left 3x3 values into the given mat3.
50 *
51 * @param {mat3} out the receiving 3x3 matrix
52 * @param {mat4} a   the source 4x4 matrix
53 * @returns {mat3} out
54 */
55mat3.fromMat4 = function(out, a) {
56    out[0] = a[0];
57    out[1] = a[1];
58    out[2] = a[2];
59    out[3] = a[4];
60    out[4] = a[5];
61    out[5] = a[6];
62    out[6] = a[8];
63    out[7] = a[9];
64    out[8] = a[10];
65    return out;
66};
67
68/**
69 * Creates a new mat3 initialized with values from an existing matrix
70 *
71 * @param {mat3} a matrix to clone
72 * @returns {mat3} a new 3x3 matrix
73 */
74mat3.clone = function(a) {
75    var out = new glMatrix.ARRAY_TYPE(9);
76    out[0] = a[0];
77    out[1] = a[1];
78    out[2] = a[2];
79    out[3] = a[3];
80    out[4] = a[4];
81    out[5] = a[5];
82    out[6] = a[6];
83    out[7] = a[7];
84    out[8] = a[8];
85    return out;
86};
87
88/**
89 * Copy the values from one mat3 to another
90 *
91 * @param {mat3} out the receiving matrix
92 * @param {mat3} a the source matrix
93 * @returns {mat3} out
94 */
95mat3.copy = function(out, a) {
96    out[0] = a[0];
97    out[1] = a[1];
98    out[2] = a[2];
99    out[3] = a[3];
100    out[4] = a[4];
101    out[5] = a[5];
102    out[6] = a[6];
103    out[7] = a[7];
104    out[8] = a[8];
105    return out;
106};
107
108/**
109 * Set a mat3 to the identity matrix
110 *
111 * @param {mat3} out the receiving matrix
112 * @returns {mat3} out
113 */
114mat3.identity = function(out) {
115    out[0] = 1;
116    out[1] = 0;
117    out[2] = 0;
118    out[3] = 0;
119    out[4] = 1;
120    out[5] = 0;
121    out[6] = 0;
122    out[7] = 0;
123    out[8] = 1;
124    return out;
125};
126
127/**
128 * Transpose the values of a mat3
129 *
130 * @param {mat3} out the receiving matrix
131 * @param {mat3} a the source matrix
132 * @returns {mat3} out
133 */
134mat3.transpose = function(out, a) {
135    // If we are transposing ourselves we can skip a few steps but have to cache some values
136    if (out === a) {
137        var a01 = a[1], a02 = a[2], a12 = a[5];
138        out[1] = a[3];
139        out[2] = a[6];
140        out[3] = a01;
141        out[5] = a[7];
142        out[6] = a02;
143        out[7] = a12;
144    } else {
145        out[0] = a[0];
146        out[1] = a[3];
147        out[2] = a[6];
148        out[3] = a[1];
149        out[4] = a[4];
150        out[5] = a[7];
151        out[6] = a[2];
152        out[7] = a[5];
153        out[8] = a[8];
154    }
155
156    return out;
157};
158
159/**
160 * Inverts a mat3
161 *
162 * @param {mat3} out the receiving matrix
163 * @param {mat3} a the source matrix
164 * @returns {mat3} out
165 */
166mat3.invert = function(out, a) {
167    var a00 = a[0], a01 = a[1], a02 = a[2],
168        a10 = a[3], a11 = a[4], a12 = a[5],
169        a20 = a[6], a21 = a[7], a22 = a[8],
170
171        b01 = a22 * a11 - a12 * a21,
172        b11 = -a22 * a10 + a12 * a20,
173        b21 = a21 * a10 - a11 * a20,
174
175        // Calculate the determinant
176        det = a00 * b01 + a01 * b11 + a02 * b21;
177
178    if (!det) {
179        return null;
180    }
181    det = 1.0 / det;
182
183    out[0] = b01 * det;
184    out[1] = (-a22 * a01 + a02 * a21) * det;
185    out[2] = (a12 * a01 - a02 * a11) * det;
186    out[3] = b11 * det;
187    out[4] = (a22 * a00 - a02 * a20) * det;
188    out[5] = (-a12 * a00 + a02 * a10) * det;
189    out[6] = b21 * det;
190    out[7] = (-a21 * a00 + a01 * a20) * det;
191    out[8] = (a11 * a00 - a01 * a10) * det;
192    return out;
193};
194
195/**
196 * Calculates the adjugate of a mat3
197 *
198 * @param {mat3} out the receiving matrix
199 * @param {mat3} a the source matrix
200 * @returns {mat3} out
201 */
202mat3.adjoint = function(out, a) {
203    var a00 = a[0], a01 = a[1], a02 = a[2],
204        a10 = a[3], a11 = a[4], a12 = a[5],
205        a20 = a[6], a21 = a[7], a22 = a[8];
206
207    out[0] = (a11 * a22 - a12 * a21);
208    out[1] = (a02 * a21 - a01 * a22);
209    out[2] = (a01 * a12 - a02 * a11);
210    out[3] = (a12 * a20 - a10 * a22);
211    out[4] = (a00 * a22 - a02 * a20);
212    out[5] = (a02 * a10 - a00 * a12);
213    out[6] = (a10 * a21 - a11 * a20);
214    out[7] = (a01 * a20 - a00 * a21);
215    out[8] = (a00 * a11 - a01 * a10);
216    return out;
217};
218
219/**
220 * Calculates the determinant of a mat3
221 *
222 * @param {mat3} a the source matrix
223 * @returns {Number} determinant of a
224 */
225mat3.determinant = function (a) {
226    var a00 = a[0], a01 = a[1], a02 = a[2],
227        a10 = a[3], a11 = a[4], a12 = a[5],
228        a20 = a[6], a21 = a[7], a22 = a[8];
229
230    return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
231};
232
233/**
234 * Multiplies two mat3's
235 *
236 * @param {mat3} out the receiving matrix
237 * @param {mat3} a the first operand
238 * @param {mat3} b the second operand
239 * @returns {mat3} out
240 */
241mat3.multiply = function (out, a, b) {
242    var a00 = a[0], a01 = a[1], a02 = a[2],
243        a10 = a[3], a11 = a[4], a12 = a[5],
244        a20 = a[6], a21 = a[7], a22 = a[8],
245
246        b00 = b[0], b01 = b[1], b02 = b[2],
247        b10 = b[3], b11 = b[4], b12 = b[5],
248        b20 = b[6], b21 = b[7], b22 = b[8];
249
250    out[0] = b00 * a00 + b01 * a10 + b02 * a20;
251    out[1] = b00 * a01 + b01 * a11 + b02 * a21;
252    out[2] = b00 * a02 + b01 * a12 + b02 * a22;
253
254    out[3] = b10 * a00 + b11 * a10 + b12 * a20;
255    out[4] = b10 * a01 + b11 * a11 + b12 * a21;
256    out[5] = b10 * a02 + b11 * a12 + b12 * a22;
257
258    out[6] = b20 * a00 + b21 * a10 + b22 * a20;
259    out[7] = b20 * a01 + b21 * a11 + b22 * a21;
260    out[8] = b20 * a02 + b21 * a12 + b22 * a22;
261    return out;
262};
263
264/**
265 * Alias for {@link mat3.multiply}
266 * @function
267 */
268mat3.mul = mat3.multiply;
269
270/**
271 * Translate a mat3 by the given vector
272 *
273 * @param {mat3} out the receiving matrix
274 * @param {mat3} a the matrix to translate
275 * @param {vec2} v vector to translate by
276 * @returns {mat3} out
277 */
278mat3.translate = function(out, a, v) {
279    var a00 = a[0], a01 = a[1], a02 = a[2],
280        a10 = a[3], a11 = a[4], a12 = a[5],
281        a20 = a[6], a21 = a[7], a22 = a[8],
282        x = v[0], y = v[1];
283
284    out[0] = a00;
285    out[1] = a01;
286    out[2] = a02;
287
288    out[3] = a10;
289    out[4] = a11;
290    out[5] = a12;
291
292    out[6] = x * a00 + y * a10 + a20;
293    out[7] = x * a01 + y * a11 + a21;
294    out[8] = x * a02 + y * a12 + a22;
295    return out;
296};
297
298/**
299 * Rotates a mat3 by the given angle
300 *
301 * @param {mat3} out the receiving matrix
302 * @param {mat3} a the matrix to rotate
303 * @param {Number} rad the angle to rotate the matrix by
304 * @returns {mat3} out
305 */
306mat3.rotate = function (out, a, rad) {
307    var a00 = a[0], a01 = a[1], a02 = a[2],
308        a10 = a[3], a11 = a[4], a12 = a[5],
309        a20 = a[6], a21 = a[7], a22 = a[8],
310
311        s = Math.sin(rad),
312        c = Math.cos(rad);
313
314    out[0] = c * a00 + s * a10;
315    out[1] = c * a01 + s * a11;
316    out[2] = c * a02 + s * a12;
317
318    out[3] = c * a10 - s * a00;
319    out[4] = c * a11 - s * a01;
320    out[5] = c * a12 - s * a02;
321
322    out[6] = a20;
323    out[7] = a21;
324    out[8] = a22;
325    return out;
326};
327
328/**
329 * Scales the mat3 by the dimensions in the given vec2
330 *
331 * @param {mat3} out the receiving matrix
332 * @param {mat3} a the matrix to rotate
333 * @param {vec2} v the vec2 to scale the matrix by
334 * @returns {mat3} out
335 **/
336mat3.scale = function(out, a, v) {
337    var x = v[0], y = v[1];
338
339    out[0] = x * a[0];
340    out[1] = x * a[1];
341    out[2] = x * a[2];
342
343    out[3] = y * a[3];
344    out[4] = y * a[4];
345    out[5] = y * a[5];
346
347    out[6] = a[6];
348    out[7] = a[7];
349    out[8] = a[8];
350    return out;
351};
352
353/**
354 * Creates a matrix from a vector translation
355 * This is equivalent to (but much faster than):
356 *
357 *     mat3.identity(dest);
358 *     mat3.translate(dest, dest, vec);
359 *
360 * @param {mat3} out mat3 receiving operation result
361 * @param {vec2} v Translation vector
362 * @returns {mat3} out
363 */
364mat3.fromTranslation = function(out, v) {
365    out[0] = 1;
366    out[1] = 0;
367    out[2] = 0;
368    out[3] = 0;
369    out[4] = 1;
370    out[5] = 0;
371    out[6] = v[0];
372    out[7] = v[1];
373    out[8] = 1;
374    return out;
375}
376
377/**
378 * Creates a matrix from a given angle
379 * This is equivalent to (but much faster than):
380 *
381 *     mat3.identity(dest);
382 *     mat3.rotate(dest, dest, rad);
383 *
384 * @param {mat3} out mat3 receiving operation result
385 * @param {Number} rad the angle to rotate the matrix by
386 * @returns {mat3} out
387 */
388mat3.fromRotation = function(out, rad) {
389    var s = Math.sin(rad), c = Math.cos(rad);
390
391    out[0] = c;
392    out[1] = s;
393    out[2] = 0;
394
395    out[3] = -s;
396    out[4] = c;
397    out[5] = 0;
398
399    out[6] = 0;
400    out[7] = 0;
401    out[8] = 1;
402    return out;
403}
404
405/**
406 * Creates a matrix from a vector scaling
407 * This is equivalent to (but much faster than):
408 *
409 *     mat3.identity(dest);
410 *     mat3.scale(dest, dest, vec);
411 *
412 * @param {mat3} out mat3 receiving operation result
413 * @param {vec2} v Scaling vector
414 * @returns {mat3} out
415 */
416mat3.fromScaling = function(out, v) {
417    out[0] = v[0];
418    out[1] = 0;
419    out[2] = 0;
420
421    out[3] = 0;
422    out[4] = v[1];
423    out[5] = 0;
424
425    out[6] = 0;
426    out[7] = 0;
427    out[8] = 1;
428    return out;
429}
430
431/**
432 * Copies the values from a mat2d into a mat3
433 *
434 * @param {mat3} out the receiving matrix
435 * @param {mat2d} a the matrix to copy
436 * @returns {mat3} out
437 **/
438mat3.fromMat2d = function(out, a) {
439    out[0] = a[0];
440    out[1] = a[1];
441    out[2] = 0;
442
443    out[3] = a[2];
444    out[4] = a[3];
445    out[5] = 0;
446
447    out[6] = a[4];
448    out[7] = a[5];
449    out[8] = 1;
450    return out;
451};
452
453/**
454* Calculates a 3x3 matrix from the given quaternion
455*
456* @param {mat3} out mat3 receiving operation result
457* @param {quat} q Quaternion to create matrix from
458*
459* @returns {mat3} out
460*/
461mat3.fromQuat = function (out, q) {
462    var x = q[0], y = q[1], z = q[2], w = q[3],
463        x2 = x + x,
464        y2 = y + y,
465        z2 = z + z,
466
467        xx = x * x2,
468        yx = y * x2,
469        yy = y * y2,
470        zx = z * x2,
471        zy = z * y2,
472        zz = z * z2,
473        wx = w * x2,
474        wy = w * y2,
475        wz = w * z2;
476
477    out[0] = 1 - yy - zz;
478    out[3] = yx - wz;
479    out[6] = zx + wy;
480
481    out[1] = yx + wz;
482    out[4] = 1 - xx - zz;
483    out[7] = zy - wx;
484
485    out[2] = zx - wy;
486    out[5] = zy + wx;
487    out[8] = 1 - xx - yy;
488
489    return out;
490};
491
492/**
493* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
494*
495* @param {mat3} out mat3 receiving operation result
496* @param {mat4} a Mat4 to derive the normal matrix from
497*
498* @returns {mat3} out
499*/
500mat3.normalFromMat4 = function (out, a) {
501    var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
502        a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
503        a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
504        a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
505
506        b00 = a00 * a11 - a01 * a10,
507        b01 = a00 * a12 - a02 * a10,
508        b02 = a00 * a13 - a03 * a10,
509        b03 = a01 * a12 - a02 * a11,
510        b04 = a01 * a13 - a03 * a11,
511        b05 = a02 * a13 - a03 * a12,
512        b06 = a20 * a31 - a21 * a30,
513        b07 = a20 * a32 - a22 * a30,
514        b08 = a20 * a33 - a23 * a30,
515        b09 = a21 * a32 - a22 * a31,
516        b10 = a21 * a33 - a23 * a31,
517        b11 = a22 * a33 - a23 * a32,
518
519        // Calculate the determinant
520        det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
521
522    if (!det) {
523        return null;
524    }
525    det = 1.0 / det;
526
527    out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
528    out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
529    out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
530
531    out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
532    out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
533    out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
534
535    out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
536    out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
537    out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
538
539    return out;
540};
541
542/**
543 * Returns a string representation of a mat3
544 *
545 * @param {mat3} mat matrix to represent as a string
546 * @returns {String} string representation of the matrix
547 */
548mat3.str = function (a) {
549    return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
550                    a[3] + ', ' + a[4] + ', ' + a[5] + ', ' +
551                    a[6] + ', ' + a[7] + ', ' + a[8] + ')';
552};
553
554/**
555 * Returns Frobenius norm of a mat3
556 *
557 * @param {mat3} a the matrix to calculate Frobenius norm of
558 * @returns {Number} Frobenius norm
559 */
560mat3.frob = function (a) {
561    return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2)))
562};
563
564
565module.exports = mat3;
566