1 /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
3 Redistribution and use in source and binary forms, with or without modification,
4 are permitted provided that the following conditions are met:
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.
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. */
30 * Creates a new identity mat4
32 * @returns {mat4} a new 4x4 matrix
34 mat4.create = function() {
35 var out = new GLMAT_ARRAY_TYPE(16);
56 * Creates a new mat4 initialized with values from an existing matrix
58 * @param {mat4} a matrix to clone
59 * @returns {mat4} a new 4x4 matrix
61 mat4.clone = function(a) {
62 var out = new GLMAT_ARRAY_TYPE(16);
83 * Copy the values from one mat4 to another
85 * @param {mat4} out the receiving matrix
86 * @param {mat4} a the source matrix
89 mat4.copy = function(out, a) {
110 * Set a mat4 to the identity matrix
112 * @param {mat4} out the receiving matrix
113 * @returns {mat4} out
115 mat4.identity = function(out) {
136 * Transpose the values of a mat4
138 * @param {mat4} out the receiving matrix
139 * @param {mat4} a the source matrix
140 * @returns {mat4} out
142 mat4.transpose = function(out, a) {
143 // If we are transposing ourselves we can skip a few steps but have to cache some values
145 var a01 = a[1], a02 = a[2], a03 = a[3],
146 a12 = a[6], a13 = a[7],
186 * @param {mat4} out the receiving matrix
187 * @param {mat4} a the source matrix
188 * @returns {mat4} out
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],
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,
209 // Calculate the determinant
210 det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
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;
238 * Calculates the adjugate of a mat4
240 * @param {mat4} out the receiving matrix
241 * @param {mat4} a the source matrix
242 * @returns {mat4} out
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];
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));
270 * Calculates the determinant of a mat4
272 * @param {mat4} a the source matrix
273 * @returns {Number} determinant of a
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],
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;
294 // Calculate the determinant
295 return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
299 * Multiplies two mat4's
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
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];
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;
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;
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;
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;
340 * Alias for {@link mat4.multiply}
343 mat4.mul = mat4.multiply;
346 * Translate a mat4 by the given vector
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
353 mat4.translate = function (out, a, v) {
354 var x = v[0], y = v[1], z = v[2],
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];
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];
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;
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];
383 * Scales the mat4 by the dimensions in the given vec3
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
390 mat4.scale = function(out, a, v) {
391 var x = v[0], y = v[1], z = v[2];
413 * Rotates a mat4 by the given angle
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
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),
432 if (Math.abs(len) < GLMAT_EPSILON) { return null; }
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];
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;
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;
466 if (a !== out) { // If the source and destination differ, copy the unchanged last row
476 * Rotates a matrix by the given angle around the X axis
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
483 mat4.rotateX = function (out, a, rad) {
484 var s = Math.sin(rad),
495 if (a !== out) { // If the source and destination differ, copy the unchanged rows
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;
519 * Rotates a matrix by the given angle around the Y axis
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
526 mat4.rotateY = function (out, a, rad) {
527 var s = Math.sin(rad),
538 if (a !== out) { // If the source and destination differ, copy the unchanged rows
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;
562 * Rotates a matrix by the given angle around the Z axis
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
569 mat4.rotateZ = function (out, a, rad) {
570 var s = Math.sin(rad),
581 if (a !== out) { // If the source and destination differ, copy the unchanged last row
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;
605 * Creates a matrix from a quaternion rotation and vector translation
606 * This is equivalent to (but much faster than):
608 * mat4.identity(dest);
609 * mat4.translate(dest, vec);
610 * var quatMat = mat4.create();
611 * quat4.toMat4(quat, quatMat);
612 * mat4.multiply(dest, quatMat);
614 * @param {mat4} out mat4 receiving operation result
615 * @param {quat4} q Rotation quaternion
616 * @param {vec3} v Translation vector
617 * @returns {mat4} out
619 mat4.fromRotationTranslation = function (out, q, v) {
621 var x = q[0], y = q[1], z = q[2], w = q[3],
636 out[0] = 1 - (yy + zz);
641 out[5] = 1 - (xx + zz);
646 out[10] = 1 - (xx + yy);
657 * Calculates a 4x4 matrix from the given quaternion
659 * @param {mat4} out mat4 receiving operation result
660 * @param {quat} q Quaternion to create matrix from
662 * @returns {mat4} out
664 mat4.fromQuat = function (out, q) {
665 var x = q[0], y = q[1], z = q[2], w = q[3],
680 out[0] = 1 - (yy + zz);
686 out[5] = 1 - (xx + zz);
692 out[10] = 1 - (xx + yy);
704 * Generates a frustum matrix with the given bounds
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
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;
724 out[5] = (near * 2) * tb;
727 out[8] = (right + left) * rl;
728 out[9] = (top + bottom) * tb;
729 out[10] = (far + near) * nf;
733 out[14] = (far * near * 2) * nf;
739 * Generates a perspective projection matrix with the given bounds
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
748 mat4.perspective = function (out, fovy, aspect, near, far) {
749 var f = 1.0 / Math.tan(fovy / 2),
750 nf = 1 / (near - far);
761 out[10] = (far + near) * nf;
765 out[14] = (2 * far * near) * nf;
771 * Generates a orthogonal projection matrix with the given bounds
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
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);
798 out[12] = (left + right) * lr;
799 out[13] = (top + bottom) * bt;
800 out[14] = (far + near) * nf;
806 * Generates a look-at matrix with the given eye position, focal point, and up axis
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
814 mat4.lookAt = function (out, eye, center, up) {
815 var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
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);
836 len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
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);
856 y0 = z1 * x2 - z2 * x1;
857 y1 = z2 * x0 - z0 * x2;
858 y2 = z0 * x1 - z1 * x0;
860 len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
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);
893 * Returns a string representation of a mat4
895 * @param {mat4} mat matrix to represent as a string
896 * @returns {String} string representation of the matrix
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] + ')';
905 if(typeof(exports) !== 'undefined') {