3 * Copyright (c) 2010 Mozilla Corporation
4 * Copyright (c) 2010 Vladimir Vukicevic
5 * Copyright (c) 2013 John Mayer
7 * Permission is hereby granted, free of charge, to any person
8 * obtaining a copy of this software and associated documentation
9 * files (the "Software"), to deal in the Software without
10 * restriction, including without limitation the rights to use,
11 * copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
32 * Vector and Matrix math utilities for JavaScript, optimized for WebGL.
33 * Edited to work with Elm Programming Language
37Elm.Native.MJS.make = function(elm) {
39 elm.Native = elm.Native || {};
40 elm.Native.MJS = elm.Native.MJS || {};
41 if (elm.Native.MJS.values) return elm.Native.MJS.values;
44 * Constant: MJS_VERSION
46 * mjs version number aa.bb.cc, encoded as an integer of the form:
49 const MJS_VERSION = 0x000000;
52 * Constant: MJS_DO_ASSERT
54 * Enables or disables runtime assertions.
56 * For potentially more performance, the assert methods can be
57 * commented out in each place where they are called.
59 const MJS_DO_ASSERT = true;
62 * Constant: MJS_FLOAT_ARRAY_TYPE
64 * The base float array type. By default, WebGLFloatArray.
66 * mjs can work with any array-like elements, but if an array
67 * creation is requested, it will create an array of the type
68 * MJS_FLOAT_ARRAY_TYPE. Also, the builtin constants such as (M4x4.I)
69 * will be of this type.
71 //const MJS_FLOAT_ARRAY_TYPE = WebGLFloatArray;
72 const MJS_FLOAT_ARRAY_TYPE = Float32Array;
73 //const MJS_FLOAT_ARRAY_TYPE = Float64Array;
74 //const MJS_FLOAT_ARRAY_TYPE = Array;
77 function MathUtils_assert(cond, msg) {
79 throw "Assertion failed: " + msg;
82 function MathUtils_assert() { }
88 * Methods for working with 3-element vectors. A vector is represented by a 3-element array.
89 * Any valid JavaScript array type may be used, but if new
90 * vectors are created they are created using the configured MJS_FLOAT_ARRAY_TYPE.
95 V3._temp1 = new MJS_FLOAT_ARRAY_TYPE(3);
96 V3._temp2 = new MJS_FLOAT_ARRAY_TYPE(3);
97 V3._temp3 = new MJS_FLOAT_ARRAY_TYPE(3);
99 if (MJS_FLOAT_ARRAY_TYPE == Array) {
100 V3.x = [1.0, 0.0, 0.0];
101 V3.y = [0.0, 1.0, 0.0];
102 V3.z = [0.0, 0.0, 1.0];
104 V3.$ = function V3_$(x, y, z) {
108 V3.clone = function V3_clone(a) {
109 //MathUtils_assert(a.length == 3, "a.length == 3");
110 return [a[0], a[1], a[2]];
113 V3.x = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0]);
114 V3.y = new MJS_FLOAT_ARRAY_TYPE([0.0, 1.0, 0.0]);
115 V3.z = new MJS_FLOAT_ARRAY_TYPE([0.0, 0.0, 1.0]);
120 * Creates a new 3-element vector with the given values.
124 * x,y,z - the 3 elements of the new vector.
128 * A new vector containing with the given argument values.
131 V3.$ = function V3_$(x, y, z) {
132 return new MJS_FLOAT_ARRAY_TYPE([x, y, z]);
138 * Clone the given 3-element vector.
142 * a - the 3-element vector to clone
146 * A new vector with the same values as the passed-in one.
149 V3.clone = function V3_clone(a) {
150 //MathUtils_assert(a.length == 3, "a.length == 3");
151 return new MJS_FLOAT_ARRAY_TYPE(a);
165 * a - the first vector operand
166 * b - the second vector operand
167 * r - optional vector to store the result in
171 * If r is specified, returns r after performing the operation.
172 * Otherwise, returns a new 3-element vector with the result.
174 V3.add = function V3_add(a, b, r) {
175 //MathUtils_assert(a.length == 3, "a.length == 3");
176 //MathUtils_assert(b.length == 3, "b.length == 3");
177 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
180 r = new MJS_FLOAT_ARRAY_TYPE(3);
195 * a - the first vector operand
196 * b - the second vector operand
197 * r - optional vector to store the result in
201 * If r is specified, returns r after performing the operation.
202 * Otherwise, returns a new 3-element vector with the result.
204 V3.sub = function V3_sub(a, b, r) {
205 //MathUtils_assert(a.length == 3, "a.length == 3");
206 //MathUtils_assert(b.length == 3, "b.length == 3");
207 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
210 r = new MJS_FLOAT_ARRAY_TYPE(3);
225 * a - the vector operand
226 * r - optional vector to store the result in
230 * If r is specified, returns r after performing the operation.
231 * Otherwise, returns a new 3-element vector with the result.
233 V3.neg = function V3_neg(a, r) {
234 //MathUtils_assert(a.length == 3, "a.length == 3");
235 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
238 r = new MJS_FLOAT_ARRAY_TYPE(3);
246 * Function: V3.direction
249 * r = (a - b) / |a - b|. The result is the normalized
250 * direction from a to b.
254 * a - the first vector operand
255 * b - the second vector operand
256 * r - optional vector to store the result in
260 * If r is specified, returns r after performing the operation.
261 * Otherwise, returns a new 3-element vector with the result.
263 V3.direction = function V3_direction(a, b, r) {
264 //MathUtils_assert(a.length == 3, "a.length == 3");
265 //MathUtils_assert(b.length == 3, "b.length == 3");
266 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
269 r = new MJS_FLOAT_ARRAY_TYPE(3);
270 return V3.normalize(V3.sub(a, b, r), r);
274 * Function: V3.length
280 * a - the vector operand
284 * The length of the given vector.
286 V3.length = function V3_length(a) {
287 //MathUtils_assert(a.length == 3, "a.length == 3");
289 return Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
293 * Function: V3.lengthSquard
295 * Perform r = |a|*|a|.
299 * a - the vector operand
303 * The square of the length of the given vector.
305 V3.lengthSquared = function V3_lengthSquared(a) {
306 //MathUtils_assert(a.length == 3, "a.length == 3");
308 return a[0]*a[0] + a[1]*a[1] + a[2]*a[2];
312 * Function: V3.normalize
314 * Perform r = a / |a|.
318 * a - the vector operand
319 * r - optional vector to store the result in
323 * If r is specified, returns r after performing the operation.
324 * Otherwise, returns a new 3-element vector with the result.
326 V3.normalize = function V3_normalize(a, r) {
327 //MathUtils_assert(a.length == 3, "a.length == 3");
328 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
331 r = new MJS_FLOAT_ARRAY_TYPE(3);
332 var im = 1.0 / V3.length(a);
346 * a - the vector operand
348 * r - optional vector to store the result in
352 * If r is specified, returns r after performing the operation.
353 * Otherwise, returns a new 3-element vector with the result.
355 V3.scale = function V3_scale(a, k, r) {
356 //MathUtils_assert(a.length == 3, "a.length == 3");
357 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
360 r = new MJS_FLOAT_ARRAY_TYPE(3);
375 * a - the first vector operand
376 * b - the second vector operand
380 * The dot product of a and b.
382 V3.dot = function V3_dot(a, b) {
383 //MathUtils_assert(a.length == 3, "a.length == 3");
384 //MathUtils_assert(b.length == 3, "b.length == 3");
398 * a - the first vector operand
399 * b - the second vector operand
400 * r - optional vector to store the result in
404 * If r is specified, returns r after performing the operation.
405 * Otherwise, returns a new 3-element vector with the result.
407 V3.cross = function V3_cross(a, b, r) {
408 //MathUtils_assert(a.length == 3, "a.length == 3");
409 //MathUtils_assert(b.length == 3, "b.length == 3");
410 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
413 r = new MJS_FLOAT_ARRAY_TYPE(3);
414 r[0] = a[1]*b[2] - a[2]*b[1];
415 r[1] = a[2]*b[0] - a[0]*b[2];
416 r[2] = a[0]*b[1] - a[1]*b[0];
421 * Function: V3.mul4x4
428 * m - the 4x4 matrix operand
429 * v - the 3-element vector operand
430 * r - optional vector to store the result in
434 * If r is specified, returns r after performing the operation.
435 * Otherwise, returns a new 3-element vector with the result.
436 * The 4-element result vector is divided by the w component
437 * and returned as a 3-element vector.
439 V3.mul4x4 = function V3_mul4x4(m, v, r) {
440 //MathUtils_assert(m.length == 16, "m.length == 16");
441 //MathUtils_assert(v.length == 3, "v.length == 3");
442 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
447 r = new MJS_FLOAT_ARRAY_TYPE(3);
451 w = V3.dot(v, tmp) + m[15];
455 r[0] = (V3.dot(v, tmp) + m[12])/w;
459 r[1] = (V3.dot(v, tmp) + m[13])/w;
463 r[2] = (V3.dot(v, tmp) + m[14])/w;
470 * Methods for working with 4x4 matrices. A matrix is represented by a 16-element array
471 * in column-major order. Any valid JavaScript array type may be used, but if new
472 * matrices are created they are created using the configured MJS_FLOAT_ARRAY_TYPE.
477 M4x4._temp1 = new MJS_FLOAT_ARRAY_TYPE(16);
478 M4x4._temp2 = new MJS_FLOAT_ARRAY_TYPE(16);
480 if (MJS_FLOAT_ARRAY_TYPE == Array) {
481 M4x4.I = [1.0, 0.0, 0.0, 0.0,
486 M4x4.$ = function M4x4_$(m00, m01, m02, m03,
491 return [m00, m01, m02, m03,
497 M4x4.clone = function M4x4_clone(m) {
498 //MathUtils_assert(m.length == 16, "m.length == 16");
499 return new [m[0], m[1], m[2], m[3],
500 m[4], m[5], m[6], m[7],
501 m[8], m[9], m[10], m[11],
502 m[12], m[13], m[14], m[15]];
505 M4x4.I = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0, 0.0,
508 0.0, 0.0, 0.0, 1.0]);
513 * Creates a new 4x4 matrix with the given values.
517 * m00..m15 - the 16 elements of the new matrix.
521 * A new matrix filled with the given argument values.
523 M4x4.$ = function M4x4_$(m00, m01, m02, m03,
528 return new MJS_FLOAT_ARRAY_TYPE([m00, m01, m02, m03,
531 m12, m13, m14, m15]);
535 * Function: M4x4.clone
537 * Clone the given 4x4 matrix.
541 * m - the 4x4 matrix to clone
545 * A new matrix with the same values as the passed-in one.
547 M4x4.clone = function M4x4_clone(m) {
548 //MathUtils_assert(m.length == 16, "m.length == 16");
549 return new MJS_FLOAT_ARRAY_TYPE(m);
553 M4x4.identity = M4x4.I;
556 * Function: M4x4.topLeft3x3
558 * Return the top left 3x3 matrix from the given 4x4 matrix m.
563 * r - optional 3x3 matrix to store the result in
567 * If r is specified, returns r after performing the operation.
568 * Otherwise, returns a new 3x3 matrix with the result.
570 M4x4.topLeft3x3 = function M4x4_topLeft3x3(m, r) {
571 //MathUtils_assert(m.length == 16, "m.length == 16");
572 //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
575 r = new MJS_FLOAT_ARRAY_TYPE(9);
576 r[0] = m[0]; r[1] = m[1]; r[2] = m[2];
577 r[3] = m[4]; r[4] = m[5]; r[5] = m[6];
578 r[6] = m[8]; r[7] = m[9]; r[8] = m[10];
583 * Function: M4x4.inverseOrthonormal
585 * Computes the inverse of the given matrix m, assuming that
586 * the matrix is orthonormal.
591 * r - optional 4x4 matrix to store the result in
595 * If r is specified, returns r after performing the operation.
596 * Otherwise, returns a new 4x4 matrix with the result.
598 M4x4.inverseOrthonormal = function M4x4_inverseOrthonormal(m, r) {
599 //MathUtils_assert(m.length == 16, "m.length == 16");
600 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
601 //MathUtils_assert(m != r, "m != r");
604 r = new MJS_FLOAT_ARRAY_TYPE(16);
605 M4x4.transpose(m, r);
606 var t = [m[12], m[13], m[14]];
607 r[3] = r[7] = r[11] = 0;
608 r[12] = -V3.dot([r[0], r[4], r[8]], t);
609 r[13] = -V3.dot([r[1], r[5], r[9]], t);
610 r[14] = -V3.dot([r[2], r[6], r[10]], t);
615 * Function: M4x4.inverseTo3x3
617 * Computes the inverse of the given matrix m, but calculates
618 * only the top left 3x3 values of the result.
623 * r - optional 3x3 matrix to store the result in
627 * If r is specified, returns r after performing the operation.
628 * Otherwise, returns a new 3x3 matrix with the result.
630 M4x4.inverseTo3x3 = function M4x4_inverseTo3x3(m, r) {
631 //MathUtils_assert(m.length == 16, "m.length == 16");
632 //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
635 r = new MJS_FLOAT_ARRAY_TYPE(9);
637 var a11 = m[10]*m[5]-m[6]*m[9],
638 a21 = -m[10]*m[1]+m[2]*m[9],
639 a31 = m[6]*m[1]-m[2]*m[5],
640 a12 = -m[10]*m[4]+m[6]*m[8],
641 a22 = m[10]*m[0]-m[2]*m[8],
642 a32 = -m[6]*m[0]+m[2]*m[4],
643 a13 = m[9]*m[4]-m[5]*m[8],
644 a23 = -m[9]*m[0]+m[1]*m[8],
645 a33 = m[5]*m[0]-m[1]*m[4];
646 var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13);
647 if (det == 0) // no inverse
648 throw "matrix not invertible";
649 var idet = 1.0 / det;
665 * Function: M4x4.makeFrustum
667 * Creates a matrix for a projection frustum with the given parameters.
671 * left - the left coordinate of the frustum
672 * right- the right coordinate of the frustum
673 * bottom - the bottom coordinate of the frustum
674 * top - the top coordinate of the frustum
675 * znear - the near z distance of the frustum
676 * zfar - the far z distance of the frustum
677 * r - optional 4x4 matrix to store the result in
681 * If r is specified, returns r after creating the projection matrix.
682 * Otherwise, returns a new 4x4 matrix.
684 M4x4.makeFrustum = function M4x4_makeFrustum(left, right, bottom, top, znear, zfar, r) {
685 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
688 r = new MJS_FLOAT_ARRAY_TYPE(16);
690 var X = 2*znear/(right-left);
691 var Y = 2*znear/(top-bottom);
692 var A = (right+left)/(right-left);
693 var B = (top+bottom)/(top-bottom);
694 var C = -(zfar+znear)/(zfar-znear);
695 var D = -2*zfar*znear/(zfar-znear);
697 r[0] = 2*znear/(right-left);
702 r[5] = 2*znear/(top-bottom);
705 r[8] = (right+left)/(right-left);
706 r[9] = (top+bottom)/(top-bottom);
707 r[10] = -(zfar+znear)/(zfar-znear);
711 r[14] = -2*zfar*znear/(zfar-znear);
718 * Function: M4x4.makePerspective
720 * Creates a matrix for a perspective projection with the given parameters.
724 * fovy - field of view in the y axis, in degrees
725 * aspect - aspect ratio
726 * znear - the near z distance of the projection
727 * zfar - the far z distance of the projection
728 * r - optional 4x4 matrix to store the result in
732 * If r is specified, returns r after creating the projection matrix.
733 * Otherwise, returns a new 4x4 matrix.
735 M4x4.makePerspective = function M4x4_makePerspective (fovy, aspect, znear, zfar, r) {
736 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
738 var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
740 var xmin = ymin * aspect;
741 var xmax = ymax * aspect;
743 return M4x4.makeFrustum(xmin, xmax, ymin, ymax, znear, zfar, r);
747 * Function: M4x4.makeOrtho
749 * Creates a matrix for an orthogonal frustum projection with the given parameters.
753 * left - the left coordinate of the frustum
754 * right- the right coordinate of the frustum
755 * bottom - the bottom coordinate of the frustum
756 * top - the top coordinate of the frustum
757 * znear - the near z distance of the frustum
758 * zfar - the far z distance of the frustum
759 * r - optional 4x4 matrix to store the result in
763 * If r is specified, returns r after creating the projection matrix.
764 * Otherwise, returns a new 4x4 matrix.
766 M4x4.makeOrtho = function M4x4_makeOrtho (left, right, bottom, top, znear, zfar, r) {
767 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
770 r = new MJS_FLOAT_ARRAY_TYPE(16);
772 var tX = -(right+left)/(right-left);
773 var tY = -(top+bottom)/(top-bottom);
774 var tZ = -(zfar+znear)/(zfar-znear);
775 var X = 2 / (right-left);
776 var Y = 2 / (top-bottom);
777 var Z = -2 / (zfar-znear);
779 r[0] = 2 / (right-left);
784 r[5] = 2 / (top-bottom);
789 r[10] = -2 / (zfar-znear);
791 r[12] = -(right+left)/(right-left);
792 r[13] = -(top+bottom)/(top-bottom);
793 r[14] = -(zfar+znear)/(zfar-znear);
800 * Function: M4x4.makeOrtho2D
802 * Creates a matrix for a 2D orthogonal frustum projection with the given parameters.
803 * znear and zfar are assumed to be -1 and 1, respectively.
807 * left - the left coordinate of the frustum
808 * right- the right coordinate of the frustum
809 * bottom - the bottom coordinate of the frustum
810 * top - the top coordinate of the frustum
811 * r - optional 4x4 matrix to store the result in
815 * If r is specified, returns r after creating the projection matrix.
816 * Otherwise, returns a new 4x4 matrix.
818 M4x4.makeOrtho2D = function M4x4_makeOrtho2D (left, right, bottom, top, r) {
819 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
821 return M4x4.makeOrtho(left, right, bottom, top, -1, 1, r);
827 * Performs r = a * b.
831 * a - the first matrix operand
832 * b - the second matrix operand
833 * r - optional 4x4 matrix to store the result in
837 * If r is specified, returns r after performing the operation.
838 * Otherwise, returns a new 4x4 matrix with the result.
840 M4x4.mul = function M4x4_mul(a, b, r) {
841 //MathUtils_assert(a.length == 16, "a.length == 16");
842 //MathUtils_assert(b.length == 16, "b.length == 16");
843 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
844 //MathUtils_assert(a != r && b != r, "a != r && b != r");
847 r = new MJS_FLOAT_ARRAY_TYPE(16);
883 r[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
884 r[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
885 r[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
886 r[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
887 r[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
888 r[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
889 r[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
890 r[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
891 r[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
892 r[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
893 r[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
894 r[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
895 r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
896 r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
897 r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
898 r[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
904 * Function: M4x4.mulAffine
906 * Performs r = a * b, assuming a and b are affine (elements 3,7,11,15 = 0,0,0,1)
910 * a - the first matrix operand
911 * b - the second matrix operand
912 * r - optional 4x4 matrix to store the result in
916 * If r is specified, returns r after performing the operation.
917 * Otherwise, returns a new 4x4 matrix with the result.
919 M4x4.mulAffine = function M4x4_mulAffine(a, b, r) {
920 //MathUtils_assert(a.length == 16, "a.length == 16");
921 //MathUtils_assert(b.length == 16, "b.length == 16");
922 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
923 //MathUtils_assert(a != r && b != r, "a != r && b != r");
926 r = new MJS_FLOAT_ARRAY_TYPE(16);
953 r[0] = a11 * b11 + a12 * b21 + a13 * b31;
954 r[1] = a21 * b11 + a22 * b21 + a23 * b31;
955 r[2] = a31 * b11 + a32 * b21 + a33 * b31;
957 r[4] = a11 * b12 + a12 * b22 + a13 * b32;
958 r[5] = a21 * b12 + a22 * b22 + a23 * b32;
959 r[6] = a31 * b12 + a32 * b22 + a33 * b32;
961 r[8] = a11 * b13 + a12 * b23 + a13 * b33;
962 r[9] = a21 * b13 + a22 * b23 + a23 * b33;
963 r[10] = a31 * b13 + a32 * b23 + a33 * b33;
965 r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14;
966 r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24;
967 r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34;
974 * Function: M4x4.makeRotate
976 * Creates a transformation matrix for rotation by angle radians about the 3-element vector axis.
980 * angle - the angle of rotation, in radians
981 * axis - the axis around which the rotation is performed, a 3-element vector
982 * r - optional 4x4 matrix to store the result in
986 * If r is specified, returns r after creating the matrix.
987 * Otherwise, returns a new 4x4 matrix with the result.
989 M4x4.makeRotate = function M4x4_makeRotate(angle, axis, r) {
990 //MathUtils_assert(angle.length == 3, "angle.length == 3");
991 //MathUtils_assert(axis.length == 3, "axis.length == 3");
992 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
995 r = new MJS_FLOAT_ARRAY_TYPE(16);
997 axis = V3.normalize(axis, V3._temp1);
998 var x = axis[0], y = axis[1], z = axis[2];
999 var c = Math.cos(angle);
1001 var s = Math.sin(angle);
1024 * Function: M4x4.rotate
1026 * Concatenates a rotation of angle radians about the axis to the give matrix m.
1030 * angle - the angle of rotation, in radians
1031 * axis - the axis around which the rotation is performed, a 3-element vector
1032 * m - the matrix to concatenate the rotation to
1033 * r - optional 4x4 matrix to store the result in
1037 * If r is specified, returns r after performing the operation.
1038 * Otherwise, returns a new 4x4 matrix with the result.
1040 M4x4.rotate = function M4x4_rotate(angle, axis, m, r) {
1041 //MathUtils_assert(angle.length == 3, "angle.length == 3");
1042 //MathUtils_assert(axis.length == 3, "axis.length == 3");
1043 //MathUtils_assert(m.length == 16, "m.length == 16");
1044 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1047 r = new MJS_FLOAT_ARRAY_TYPE(16);
1048 var a0=axis [0], a1=axis [1], a2=axis [2];
1049 var l = Math.sqrt(a0*a0 + a1*a1 + a2*a2);
1050 var x = a0, y = a1, z = a2;
1057 var c = Math.cos(angle);
1059 var s = Math.sin(angle);
1063 var xyc1 = x * y * c1;
1064 var xzc1 = x * z * c1;
1065 var yzc1 = y * z * c1;
1080 var t11 = x * x * c1 + c;
1081 var t21 = xyc1 + zs;
1082 var t31 = xzc1 - ys;
1083 var t12 = xyc1 - zs;
1084 var t22 = y * y * c1 + c;
1085 var t32 = yzc1 + xs;
1086 var t13 = xzc1 + ys;
1087 var t23 = yzc1 - xs;
1088 var t33 = z * z * c1 + c;
1090 r[0] = m11 * t11 + m12 * t21 + m13 * t31;
1091 r[1] = m21 * t11 + m22 * t21 + m23 * t31;
1092 r[2] = m31 * t11 + m32 * t21 + m33 * t31;
1093 r[3] = m41 * t11 + m42 * t21 + m43 * t31;
1094 r[4] = m11 * t12 + m12 * t22 + m13 * t32;
1095 r[5] = m21 * t12 + m22 * t22 + m23 * t32;
1096 r[6] = m31 * t12 + m32 * t22 + m33 * t32;
1097 r[7] = m41 * t12 + m42 * t22 + m43 * t32;
1098 r[8] = m11 * t13 + m12 * t23 + m13 * t33;
1099 r[9] = m21 * t13 + m22 * t23 + m23 * t33;
1100 r[10] = m31 * t13 + m32 * t23 + m33 * t33;
1101 r[11] = m41 * t13 + m42 * t23 + m43 * t33;
1112 * Function: M4x4.makeScale3
1114 * Creates a transformation matrix for scaling by 3 scalar values, one for
1115 * each of the x, y, and z directions.
1119 * x - the scale for the x axis
1120 * y - the scale for the y axis
1121 * z - the scale for the z axis
1122 * r - optional 4x4 matrix to store the result in
1126 * If r is specified, returns r after creating the matrix.
1127 * Otherwise, returns a new 4x4 matrix with the result.
1129 M4x4.makeScale3 = function M4x4_makeScale3(x, y, z, r) {
1130 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1133 r = new MJS_FLOAT_ARRAY_TYPE(16);
1156 * Function: M4x4.makeScale1
1158 * Creates a transformation matrix for a uniform scale by a single scalar value.
1162 * k - the scale factor
1163 * r - optional 4x4 matrix to store the result in
1167 * If r is specified, returns r after creating the matrix.
1168 * Otherwise, returns a new 4x4 matrix with the result.
1170 M4x4.makeScale1 = function M4x4_makeScale1(k, r) {
1171 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1173 return M4x4.makeScale3(k, k, k, r);
1177 * Function: M4x4.makeScale
1179 * Creates a transformation matrix for scaling each of the x, y, and z axes by the amount
1180 * given in the corresponding element of the 3-element vector.
1184 * v - the 3-element vector containing the scale factors
1185 * r - optional 4x4 matrix to store the result in
1189 * If r is specified, returns r after creating the matrix.
1190 * Otherwise, returns a new 4x4 matrix with the result.
1192 M4x4.makeScale = function M4x4_makeScale(v, r) {
1193 //MathUtils_assert(v.length == 3, "v.length == 3");
1194 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1196 return M4x4.makeScale3(v[0], v[1], v[2], r);
1200 * Function: M4x4.scale3
1202 M4x4.scale3 = function M4x4_scale3(x, y, z, m, r) {
1203 //MathUtils_assert(m.length == 16, "m.length == 16");
1204 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1223 r = new MJS_FLOAT_ARRAY_TYPE(16);
1246 * Function: M4x4.scale1
1248 M4x4.scale1 = function M4x4_scale1(k, m, r) {
1249 //MathUtils_assert(m.length == 16, "m.length == 16");
1250 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1269 r = new MJS_FLOAT_ARRAY_TYPE(16);
1292 * Function: M4x4.scale1
1294 M4x4.scale = function M4x4_scale(v, m, r) {
1295 //MathUtils_assert(v.length == 3, "v.length == 3");
1296 //MathUtils_assert(m.length == 16, "m.length == 16");
1297 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1298 var x = v[0], y = v[1], z = v[2];
1317 r = new MJS_FLOAT_ARRAY_TYPE(16);
1341 * Function: M4x4.makeTranslate3
1343 M4x4.makeTranslate3 = function M4x4_makeTranslate3(x, y, z, r) {
1344 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1347 r = new MJS_FLOAT_ARRAY_TYPE(16);
1370 * Function: M4x4.makeTranslate1
1372 M4x4.makeTranslate1 = function M4x4_makeTranslate1 (k, r) {
1373 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1375 return M4x4.makeTranslate3(k, k, k, r);
1379 * Function: M4x4.makeTranslate
1381 M4x4.makeTranslate = function M4x4_makeTranslate (v, r) {
1382 //MathUtils_assert(v.length == 3, "v.length == 3");
1383 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1385 return M4x4.makeTranslate3(v[0], v[1], v[2], r);
1389 * Function: M4x4.translate3Self
1391 M4x4.translate3Self = function M4x4_translate3Self (x, y, z, m) {
1392 //MathUtils_assert(m.length == 16, "m.length == 16");
1393 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1394 m[12] += m[0] * x + m[4] * y + m[8] * z;
1395 m[13] += m[1] * x + m[5] * y + m[9] * z;
1396 m[14] += m[2] * x + m[6] * y + m[10] * z;
1397 m[15] += m[3] * x + m[7] * y + m[11] * z;
1402 * Function: M4x4.translate3
1404 M4x4.translate3 = function M4x4_translate3 (x, y, z, m, r) {
1405 //MathUtils_assert(m.length == 16, "m.length == 16");
1406 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1409 m[12] += m[0] * x + m[4] * y + m[8] * z;
1410 m[13] += m[1] * x + m[5] * y + m[9] * z;
1411 m[14] += m[2] * x + m[6] * y + m[10] * z;
1412 m[15] += m[3] * x + m[7] * y + m[11] * z;
1417 r = new MJS_FLOAT_ARRAY_TYPE(16);
1445 r[12] = m11 * x + m12 * y + m13 * z + m[12];
1446 r[13] = m21 * x + m22 * y + m23 * z + m[13];
1447 r[14] = m31 * x + m32 * y + m33 * z + m[14];
1448 r[15] = m41 * x + m42 * y + m43 * z + m[15];
1454 * Function: M4x4.translate1
1456 M4x4.translate1 = function M4x4_translate1 (k, m, r) {
1457 //MathUtils_assert(m.length == 16, "m.length == 16");
1458 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1460 return M4x4.translate3(k, k, k, m, r);
1463 * Function: M4x4.translateSelf
1465 M4x4.translateSelf = function M4x4_translateSelf (v, m) {
1466 //MathUtils_assert(v.length == 3, "v.length == 3");
1467 //MathUtils_assert(m.length == 16, "m.length == 16");
1468 var x=v[0], y=v[1], z=v[2];
1469 m[12] += m[0] * x + m[4] * y + m[8] * z;
1470 m[13] += m[1] * x + m[5] * y + m[9] * z;
1471 m[14] += m[2] * x + m[6] * y + m[10] * z;
1472 m[15] += m[3] * x + m[7] * y + m[11] * z;
1476 * Function: M4x4.translate
1478 M4x4.translate = function M4x4_translate (v, m, r) {
1479 //MathUtils_assert(v.length == 3, "v.length == 3");
1480 //MathUtils_assert(m.length == 16, "m.length == 16");
1481 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1482 var x=v[0], y=v[1], z=v[2];
1484 m[12] += m[0] * x + m[4] * y + m[8] * z;
1485 m[13] += m[1] * x + m[5] * y + m[9] * z;
1486 m[14] += m[2] * x + m[6] * y + m[10] * z;
1487 m[15] += m[3] * x + m[7] * y + m[11] * z;
1492 r = new MJS_FLOAT_ARRAY_TYPE(16);
1519 r[12] = m11 * x + m12 * y + m13 * z + m[12];
1520 r[13] = m21 * x + m22 * y + m23 * z + m[13];
1521 r[14] = m31 * x + m32 * y + m33 * z + m[14];
1522 r[15] = m41 * x + m42 * y + m43 * z + m[15];
1528 * Function: M4x4.makeLookAt
1530 M4x4.makeLookAt = function M4x4_makeLookAt (eye, center, up, r) {
1531 //MathUtils_assert(eye.length == 3, "eye.length == 3");
1532 //MathUtils_assert(center.length == 3, "center.length == 3");
1533 //MathUtils_assert(up.length == 3, "up.length == 3");
1534 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1536 var z = V3.direction(eye, center, V3._temp1);
1537 var x = V3.normalize(V3.cross(up, z, V3._temp2), V3._temp2);
1538 var y = V3.normalize(V3.cross(z, x, V3._temp3), V3._temp3);
1540 var tm1 = M4x4._temp1;
1541 var tm2 = M4x4._temp2;
1560 tm2[0] = 1; tm2[1] = 0; tm2[2] = 0; tm2[3] = 0;
1561 tm2[4] = 0; tm2[5] = 1; tm2[6] = 0; tm2[7] = 0;
1562 tm2[8] = 0; tm2[9] = 0; tm2[10] = 1; tm2[11] = 0;
1563 tm2[12] = -eye[0]; tm2[13] = -eye[1]; tm2[14] = -eye[2]; tm2[15] = 1;
1566 r = new MJS_FLOAT_ARRAY_TYPE(16);
1567 return M4x4.mul(tm1, tm2, r);
1571 * Function: M4x4.transposeSelf
1573 M4x4.transposeSelf = function M4x4_transposeSelf (m) {
1574 //MathUtils_assert(m.length == 16, "m.length == 16");
1575 var tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1576 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1577 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1578 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1579 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1580 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1584 * Function: M4x4.transpose
1586 M4x4.transpose = function M4x4_transpose (m, r) {
1587 //MathUtils_assert(m.length == 16, "m.length == 16");
1588 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1592 tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1593 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1594 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1595 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1596 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1597 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1602 r = new MJS_FLOAT_ARRAY_TYPE(16);
1604 r[0] = m[0]; r[1] = m[4]; r[2] = m[8]; r[3] = m[12];
1605 r[4] = m[1]; r[5] = m[5]; r[6] = m[9]; r[7] = m[13];
1606 r[8] = m[2]; r[9] = m[6]; r[10] = m[10]; r[11] = m[14];
1607 r[12] = m[3]; r[13] = m[7]; r[14] = m[11]; r[15] = m[15];
1614 * Function: M4x4.transformPoint
1616 M4x4.transformPoint = function M4x4_transformPoint (m, v, r) {
1617 //MathUtils_assert(m.length == 16, "m.length == 16");
1618 //MathUtils_assert(v.length == 3, "v.length == 3");
1619 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1621 r = new MJS_FLOAT_ARRAY_TYPE(3);
1623 var v0 = v[0], v1 = v[1], v2 = v[2];
1625 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1626 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1627 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1628 var w = m[3] * v0 + m[7] * v1 + m[11] * v2 + m[15];
1640 * Function: M4x4.transformLine
1642 M4x4.transformLine = function M4x4_transformLine(m, v, r) {
1643 //MathUtils_assert(m.length == 16, "m.length == 16");
1644 //MathUtils_assert(v.length == 3, "v.length == 3");
1645 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1647 r = new MJS_FLOAT_ARRAY_TYPE(3);
1649 var v0 = v[0], v1 = v[1], v2 = v[2];
1650 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1651 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1652 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1653 var w = m[3] * v0 + m[7] * v1 + m[11] * v2;
1666 * Function: M4x4.transformPointAffine
1668 M4x4.transformPointAffine = function M4x4_transformPointAffine (m, v, r) {
1669 //MathUtils_assert(m.length == 16, "m.length == 16");
1670 //MathUtils_assert(v.length == 3, "v.length == 3");
1671 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1673 r = new MJS_FLOAT_ARRAY_TYPE(3);
1675 var v0 = v[0], v1 = v[1], v2 = v[2];
1677 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1678 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1679 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1685 * Function: M4x4.transformLineAffine
1687 M4x4.transformLineAffine = function M4x4_transformLineAffine(m, v, r) {
1688 //MathUtils_assert(m.length == 16, "m.length == 16");
1689 //MathUtils_assert(v.length == 3, "v.length == 3");
1690 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1692 r = new MJS_FLOAT_ARRAY_TYPE(3);
1694 var v0 = v[0], v1 = v[1], v2 = v[2];
1695 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1696 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1697 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1702 M4x4.makeBasis = function M4x4_makeBasis(vx,vy,vz) {
1704 var r = new MJS_FLOAT_ARRAY_TYPE(16);
1733 v3direction: F2(V3.direction),
1734 v3length: V3.length,
1735 v3lengthSquared: V3.lengthSquared,
1736 v3normalize: V3.normalize,
1737 v3scale: F2(V3.scale),
1739 v3cross: F2(V3.cross),
1740 v3mul4x4: F2(V3.mul4x4),
1742 m4x4identity: M4x4.identity,
1743 m4x4topLeft3x3: M4x4.topLeft3x3,
1744 m4x4inverseOrthonormal: M4x4.inverseOrthonormal,
1745 m4x4inverseTo3x3: M4x4.inverseTo3x3,
1746 m4x4makeFrustum: F6(M4x4.makeFrustum),
1747 m4x4makePerspective: F4(M4x4.makePerspective),
1748 m4x4makeOrtho: F6(M4x4.makeOrtho),
1749 m4x4makeOrtho2D: F4(M4x4.makeOrtho2D),
1750 m4x4mul: F2(M4x4.mul),
1751 m4x4Affine: F2(M4x4.mulAffine),
1752 m4x4makeRotate: F2(M4x4.makeRotate),
1753 m4x4rotate: F3(M4x4.rotate),
1754 m4x4makeScale3: F3(M4x4.makeScale3),
1755 m4x4makeScale1: M4x4.makeScale1,
1756 m4x4makeScale: M4x4.makeScale,
1757 m4x4scale3: F4(M4x4.scale3),
1758 m4x4scale: F2(M4x4.scale),
1759 m4x4makeTranslate3: F3(M4x4.makeTranslate3),
1760 m4x4makeTranslate: M4x4.makeTranslate,
1761 m4x4translate3: F4(M4x4.translate3),
1762 m4x4translate: F2(M4x4.translate),
1763 m4x4makeLookAt: F3(M4x4.makeLookAt),
1764 m4x4transpose: M4x4.transpose,
1765 m4x4transformPoint: F2(M4x4.transformPoint),
1766 m4x4makeBasis: F3(M4x4.makeBasis),
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list