@@ -0,0 +1,1783 @@
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
37+Elm.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+ var 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+ //var 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+ //MJS_FLOAT_ARRAY_TYPE = WebGLFloatArray;
72+ var MJS_FLOAT_ARRAY_TYPE = Float32Array;
73+ //MJS_FLOAT_ARRAY_TYPE = Float64Array;
74+ //MJS_FLOAT_ARRAY_TYPE = Array;
76+ //if (MJS_DO_ASSERT) {
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]);
136+ * Function: V3.clone
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);
158+ /* Function: V3.toTuple3
160+ * Turn into an Elm Tuple
162+ V3.toTuple3 = function V3_toTuple3(a) {
174+ * Perform r = a + b.
178+ * a - the first vector operand
179+ * b - the second vector operand
180+ * r - optional vector to store the result in
184+ * If r is specified, returns r after performing the operation.
185+ * Otherwise, returns a new 3-element vector with the result.
187+ V3.add = function V3_add(a, b, r) {
188+ //MathUtils_assert(a.length == 3, "a.length == 3");
189+ //MathUtils_assert(b.length == 3, "b.length == 3");
190+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
193+ r = new MJS_FLOAT_ARRAY_TYPE(3);
208+ * a - the first vector operand
209+ * b - the second vector operand
210+ * r - optional vector to store the result in
214+ * If r is specified, returns r after performing the operation.
215+ * Otherwise, returns a new 3-element vector with the result.
217+ V3.sub = function V3_sub(a, b, r) {
218+ //MathUtils_assert(a.length == 3, "a.length == 3");
219+ //MathUtils_assert(b.length == 3, "b.length == 3");
220+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
223+ r = new MJS_FLOAT_ARRAY_TYPE(3);
238+ * a - the vector operand
239+ * r - optional vector to store the result in
243+ * If r is specified, returns r after performing the operation.
244+ * Otherwise, returns a new 3-element vector with the result.
246+ V3.neg = function V3_neg(a, r) {
247+ //MathUtils_assert(a.length == 3, "a.length == 3");
248+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
251+ r = new MJS_FLOAT_ARRAY_TYPE(3);
259+ * Function: V3.direction
262+ * r = (a - b) / |a - b|. The result is the normalized
263+ * direction from a to b.
267+ * a - the first vector operand
268+ * b - the second vector operand
269+ * r - optional vector to store the result in
273+ * If r is specified, returns r after performing the operation.
274+ * Otherwise, returns a new 3-element vector with the result.
276+ V3.direction = function V3_direction(a, b, r) {
277+ //MathUtils_assert(a.length == 3, "a.length == 3");
278+ //MathUtils_assert(b.length == 3, "b.length == 3");
279+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
282+ r = new MJS_FLOAT_ARRAY_TYPE(3);
283+ return V3.normalize(V3.sub(a, b, r), r);
287+ * Function: V3.length
293+ * a - the vector operand
297+ * The length of the given vector.
299+ V3.length = function V3_length(a) {
300+ //MathUtils_assert(a.length == 3, "a.length == 3");
302+ return Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
306+ * Function: V3.lengthSquard
308+ * Perform r = |a|*|a|.
312+ * a - the vector operand
316+ * The square of the length of the given vector.
318+ V3.lengthSquared = function V3_lengthSquared(a) {
319+ //MathUtils_assert(a.length == 3, "a.length == 3");
321+ return a[0]*a[0] + a[1]*a[1] + a[2]*a[2];
325+ * Function: V3.normalize
327+ * Perform r = a / |a|.
331+ * a - the vector operand
332+ * r - optional vector to store the result in
336+ * If r is specified, returns r after performing the operation.
337+ * Otherwise, returns a new 3-element vector with the result.
339+ V3.normalize = function V3_normalize(a, r) {
340+ //MathUtils_assert(a.length == 3, "a.length == 3");
341+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
344+ r = new MJS_FLOAT_ARRAY_TYPE(3);
345+ var im = 1.0 / V3.length(a);
353+ * Function: V3.scale
355+ * Perform r = a * k.
359+ * a - the vector operand
360+ * k - a scalar value
361+ * r - optional vector to store the result in
365+ * If r is specified, returns r after performing the operation.
366+ * Otherwise, returns a new 3-element vector with the result.
368+ V3.scale = function V3_scale(a, k, r) {
369+ //MathUtils_assert(a.length == 3, "a.length == 3");
370+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
373+ r = new MJS_FLOAT_ARRAY_TYPE(3);
388+ * a - the first vector operand
389+ * b - the second vector operand
393+ * The dot product of a and b.
395+ V3.dot = function V3_dot(a, b) {
396+ //MathUtils_assert(a.length == 3, "a.length == 3");
397+ //MathUtils_assert(b.length == 3, "b.length == 3");
399+ return a[0] * b[0] +
405+ * Function: V3.cross
407+ * Perform r = a x b.
411+ * a - the first vector operand
412+ * b - the second vector operand
413+ * r - optional vector to store the result in
417+ * If r is specified, returns r after performing the operation.
418+ * Otherwise, returns a new 3-element vector with the result.
420+ V3.cross = function V3_cross(a, b, r) {
421+ //MathUtils_assert(a.length == 3, "a.length == 3");
422+ //MathUtils_assert(b.length == 3, "b.length == 3");
423+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
426+ r = new MJS_FLOAT_ARRAY_TYPE(3);
427+ r[0] = a[1]*b[2] - a[2]*b[1];
428+ r[1] = a[2]*b[0] - a[0]*b[2];
429+ r[2] = a[0]*b[1] - a[1]*b[0];
434+ * Function: V3.mul4x4
441+ * m - the 4x4 matrix operand
442+ * v - the 3-element vector operand
443+ * r - optional vector to store the result in
447+ * If r is specified, returns r after performing the operation.
448+ * Otherwise, returns a new 3-element vector with the result.
449+ * The 4-element result vector is divided by the w component
450+ * and returned as a 3-element vector.
452+ V3.mul4x4 = function V3_mul4x4(m, v, r) {
453+ //MathUtils_assert(m.length == 16, "m.length == 16");
454+ //MathUtils_assert(v.length == 3, "v.length == 3");
455+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
458+ var tmp = V3._temp1;
460+ r = new MJS_FLOAT_ARRAY_TYPE(3);
464+ w = V3.dot(v, tmp) + m[15];
468+ r[0] = (V3.dot(v, tmp) + m[12])/w;
472+ r[1] = (V3.dot(v, tmp) + m[13])/w;
476+ r[2] = (V3.dot(v, tmp) + m[14])/w;
483+ * Methods for working with 4x4 matrices. A matrix is represented by a 16-element array
484+ * in column-major order. Any valid JavaScript array type may be used, but if new
485+ * matrices are created they are created using the configured MJS_FLOAT_ARRAY_TYPE.
490+ M4x4._temp1 = new MJS_FLOAT_ARRAY_TYPE(16);
491+ M4x4._temp2 = new MJS_FLOAT_ARRAY_TYPE(16);
493+ if (MJS_FLOAT_ARRAY_TYPE == Array) {
494+ M4x4.I = [1.0, 0.0, 0.0, 0.0,
497+ 0.0, 0.0, 0.0, 1.0];
499+ M4x4.$ = function M4x4_$(m00, m01, m02, m03,
504+ return [m00, m01, m02, m03,
507+ m12, m13, m14, m15];
510+ M4x4.clone = function M4x4_clone(m) {
511+ //MathUtils_assert(m.length == 16, "m.length == 16");
512+ return new [m[0], m[1], m[2], m[3],
513+ m[4], m[5], m[6], m[7],
514+ m[8], m[9], m[10], m[11],
515+ m[12], m[13], m[14], m[15]];
518+ M4x4.I = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0, 0.0,
521+ 0.0, 0.0, 0.0, 1.0]);
526+ * Creates a new 4x4 matrix with the given values.
530+ * m00..m15 - the 16 elements of the new matrix.
534+ * A new matrix filled with the given argument values.
536+ M4x4.$ = function M4x4_$(m00, m01, m02, m03,
541+ return new MJS_FLOAT_ARRAY_TYPE([m00, m01, m02, m03,
544+ m12, m13, m14, m15]);
548+ * Function: M4x4.clone
550+ * Clone the given 4x4 matrix.
554+ * m - the 4x4 matrix to clone
558+ * A new matrix with the same values as the passed-in one.
560+ M4x4.clone = function M4x4_clone(m) {
561+ //MathUtils_assert(m.length == 16, "m.length == 16");
562+ return new MJS_FLOAT_ARRAY_TYPE(m);
566+ M4x4.identity = M4x4.I;
569+ * Function: M4x4.topLeft3x3
571+ * Return the top left 3x3 matrix from the given 4x4 matrix m.
576+ * r - optional 3x3 matrix to store the result in
580+ * If r is specified, returns r after performing the operation.
581+ * Otherwise, returns a new 3x3 matrix with the result.
583+ M4x4.topLeft3x3 = function M4x4_topLeft3x3(m, r) {
584+ //MathUtils_assert(m.length == 16, "m.length == 16");
585+ //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
588+ r = new MJS_FLOAT_ARRAY_TYPE(9);
589+ r[0] = m[0]; r[1] = m[1]; r[2] = m[2];
590+ r[3] = m[4]; r[4] = m[5]; r[5] = m[6];
591+ r[6] = m[8]; r[7] = m[9]; r[8] = m[10];
596+ * Function: M4x4.inverseOrthonormal
598+ * Computes the inverse of the given matrix m, assuming that
599+ * the matrix is orthonormal.
604+ * r - optional 4x4 matrix to store the result in
608+ * If r is specified, returns r after performing the operation.
609+ * Otherwise, returns a new 4x4 matrix with the result.
611+ M4x4.inverseOrthonormal = function M4x4_inverseOrthonormal(m, r) {
612+ //MathUtils_assert(m.length == 16, "m.length == 16");
613+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
614+ //MathUtils_assert(m != r, "m != r");
617+ r = new MJS_FLOAT_ARRAY_TYPE(16);
618+ M4x4.transpose(m, r);
619+ var t = [m[12], m[13], m[14]];
620+ r[3] = r[7] = r[11] = 0;
621+ r[12] = -V3.dot([r[0], r[4], r[8]], t);
622+ r[13] = -V3.dot([r[1], r[5], r[9]], t);
623+ r[14] = -V3.dot([r[2], r[6], r[10]], t);
628+ * Function: M4x4.inverseTo3x3
630+ * Computes the inverse of the given matrix m, but calculates
631+ * only the top left 3x3 values of the result.
636+ * r - optional 3x3 matrix to store the result in
640+ * If r is specified, returns r after performing the operation.
641+ * Otherwise, returns a new 3x3 matrix with the result.
643+ M4x4.inverseTo3x3 = function M4x4_inverseTo3x3(m, r) {
644+ //MathUtils_assert(m.length == 16, "m.length == 16");
645+ //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
648+ r = new MJS_FLOAT_ARRAY_TYPE(9);
650+ var a11 = m[10]*m[5]-m[6]*m[9],
651+ a21 = -m[10]*m[1]+m[2]*m[9],
652+ a31 = m[6]*m[1]-m[2]*m[5],
653+ a12 = -m[10]*m[4]+m[6]*m[8],
654+ a22 = m[10]*m[0]-m[2]*m[8],
655+ a32 = -m[6]*m[0]+m[2]*m[4],
656+ a13 = m[9]*m[4]-m[5]*m[8],
657+ a23 = -m[9]*m[0]+m[1]*m[8],
658+ a33 = m[5]*m[0]-m[1]*m[4];
659+ var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13);
660+ if (det == 0) // no inverse
661+ throw "matrix not invertible";
662+ var idet = 1.0 / det;
678+ * Function: M4x4.makeFrustum
680+ * Creates a matrix for a projection frustum with the given parameters.
684+ * left - the left coordinate of the frustum
685+ * right- the right coordinate of the frustum
686+ * bottom - the bottom coordinate of the frustum
687+ * top - the top coordinate of the frustum
688+ * znear - the near z distance of the frustum
689+ * zfar - the far z distance of the frustum
690+ * r - optional 4x4 matrix to store the result in
694+ * If r is specified, returns r after creating the projection matrix.
695+ * Otherwise, returns a new 4x4 matrix.
697+ M4x4.makeFrustum = function M4x4_makeFrustum(left, right, bottom, top, znear, zfar, r) {
698+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
701+ r = new MJS_FLOAT_ARRAY_TYPE(16);
703+ var X = 2*znear/(right-left);
704+ var Y = 2*znear/(top-bottom);
705+ var A = (right+left)/(right-left);
706+ var B = (top+bottom)/(top-bottom);
707+ var C = -(zfar+znear)/(zfar-znear);
708+ var D = -2*zfar*znear/(zfar-znear);
710+ r[0] = 2*znear/(right-left);
715+ r[5] = 2*znear/(top-bottom);
718+ r[8] = (right+left)/(right-left);
719+ r[9] = (top+bottom)/(top-bottom);
720+ r[10] = -(zfar+znear)/(zfar-znear);
724+ r[14] = -2*zfar*znear/(zfar-znear);
731+ * Function: M4x4.makePerspective
733+ * Creates a matrix for a perspective projection with the given parameters.
737+ * fovy - field of view in the y axis, in degrees
738+ * aspect - aspect ratio
739+ * znear - the near z distance of the projection
740+ * zfar - the far z distance of the projection
741+ * r - optional 4x4 matrix to store the result in
745+ * If r is specified, returns r after creating the projection matrix.
746+ * Otherwise, returns a new 4x4 matrix.
748+ M4x4.makePerspective = function M4x4_makePerspective (fovy, aspect, znear, zfar, r) {
749+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
751+ var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
753+ var xmin = ymin * aspect;
754+ var xmax = ymax * aspect;
756+ return M4x4.makeFrustum(xmin, xmax, ymin, ymax, znear, zfar, r);
760+ * Function: M4x4.makeOrtho
762+ * Creates a matrix for an orthogonal frustum projection with the given parameters.
766+ * left - the left coordinate of the frustum
767+ * right- the right coordinate of the frustum
768+ * bottom - the bottom coordinate of the frustum
769+ * top - the top coordinate of the frustum
770+ * znear - the near z distance of the frustum
771+ * zfar - the far z distance of the frustum
772+ * r - optional 4x4 matrix to store the result in
776+ * If r is specified, returns r after creating the projection matrix.
777+ * Otherwise, returns a new 4x4 matrix.
779+ M4x4.makeOrtho = function M4x4_makeOrtho (left, right, bottom, top, znear, zfar, r) {
780+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
783+ r = new MJS_FLOAT_ARRAY_TYPE(16);
785+ var tX = -(right+left)/(right-left);
786+ var tY = -(top+bottom)/(top-bottom);
787+ var tZ = -(zfar+znear)/(zfar-znear);
788+ var X = 2 / (right-left);
789+ var Y = 2 / (top-bottom);
790+ var Z = -2 / (zfar-znear);
792+ r[0] = 2 / (right-left);
797+ r[5] = 2 / (top-bottom);
802+ r[10] = -2 / (zfar-znear);
804+ r[12] = -(right+left)/(right-left);
805+ r[13] = -(top+bottom)/(top-bottom);
806+ r[14] = -(zfar+znear)/(zfar-znear);
813+ * Function: M4x4.makeOrtho2D
815+ * Creates a matrix for a 2D orthogonal frustum projection with the given parameters.
816+ * znear and zfar are assumed to be -1 and 1, respectively.
820+ * left - the left coordinate of the frustum
821+ * right- the right coordinate of the frustum
822+ * bottom - the bottom coordinate of the frustum
823+ * top - the top coordinate of the frustum
824+ * r - optional 4x4 matrix to store the result in
828+ * If r is specified, returns r after creating the projection matrix.
829+ * Otherwise, returns a new 4x4 matrix.
831+ M4x4.makeOrtho2D = function M4x4_makeOrtho2D (left, right, bottom, top, r) {
832+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
834+ return M4x4.makeOrtho(left, right, bottom, top, -1, 1, r);
838+ * Function: M4x4.mul
840+ * Performs r = a * b.
844+ * a - the first matrix operand
845+ * b - the second matrix operand
846+ * r - optional 4x4 matrix to store the result in
850+ * If r is specified, returns r after performing the operation.
851+ * Otherwise, returns a new 4x4 matrix with the result.
853+ M4x4.mul = function M4x4_mul(a, b, r) {
854+ //MathUtils_assert(a.length == 16, "a.length == 16");
855+ //MathUtils_assert(b.length == 16, "b.length == 16");
856+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
857+ //MathUtils_assert(a != r && b != r, "a != r && b != r");
860+ r = new MJS_FLOAT_ARRAY_TYPE(16);
896+ r[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
897+ r[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
898+ r[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
899+ r[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
900+ r[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
901+ r[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
902+ r[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
903+ r[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
904+ r[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
905+ r[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
906+ r[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
907+ r[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
908+ r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
909+ r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
910+ r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
911+ r[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
917+ * Function: M4x4.mulAffine
919+ * Performs r = a * b, assuming a and b are affine (elements 3,7,11,15 = 0,0,0,1)
923+ * a - the first matrix operand
924+ * b - the second matrix operand
925+ * r - optional 4x4 matrix to store the result in
929+ * If r is specified, returns r after performing the operation.
930+ * Otherwise, returns a new 4x4 matrix with the result.
932+ M4x4.mulAffine = function M4x4_mulAffine(a, b, r) {
933+ //MathUtils_assert(a.length == 16, "a.length == 16");
934+ //MathUtils_assert(b.length == 16, "b.length == 16");
935+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
936+ //MathUtils_assert(a != r && b != r, "a != r && b != r");
939+ r = new MJS_FLOAT_ARRAY_TYPE(16);
966+ r[0] = a11 * b11 + a12 * b21 + a13 * b31;
967+ r[1] = a21 * b11 + a22 * b21 + a23 * b31;
968+ r[2] = a31 * b11 + a32 * b21 + a33 * b31;
970+ r[4] = a11 * b12 + a12 * b22 + a13 * b32;
971+ r[5] = a21 * b12 + a22 * b22 + a23 * b32;
972+ r[6] = a31 * b12 + a32 * b22 + a33 * b32;
974+ r[8] = a11 * b13 + a12 * b23 + a13 * b33;
975+ r[9] = a21 * b13 + a22 * b23 + a23 * b33;
976+ r[10] = a31 * b13 + a32 * b23 + a33 * b33;
978+ r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14;
979+ r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24;
980+ r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34;
987+ * Function: M4x4.makeRotate
989+ * Creates a transformation matrix for rotation by angle radians about the 3-element vector axis.
993+ * angle - the angle of rotation, in radians
994+ * axis - the axis around which the rotation is performed, a 3-element vector
995+ * r - optional 4x4 matrix to store the result in
999+ * If r is specified, returns r after creating the matrix.
1000+ * Otherwise, returns a new 4x4 matrix with the result.
1002+ M4x4.makeRotate = function M4x4_makeRotate(angle, axis, r) {
1003+ //MathUtils_assert(angle.length == 3, "angle.length == 3");
1004+ //MathUtils_assert(axis.length == 3, "axis.length == 3");
1005+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1007+ if (r == undefined)
1008+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1010+ axis = V3.normalize(axis, V3._temp1);
1011+ var x = axis[0], y = axis[1], z = axis[2];
1012+ var c = Math.cos(angle);
1014+ var s = Math.sin(angle);
1037+ * Function: M4x4.rotate
1039+ * Concatenates a rotation of angle radians about the axis to the give matrix m.
1043+ * angle - the angle of rotation, in radians
1044+ * axis - the axis around which the rotation is performed, a 3-element vector
1045+ * m - the matrix to concatenate the rotation to
1046+ * r - optional 4x4 matrix to store the result in
1050+ * If r is specified, returns r after performing the operation.
1051+ * Otherwise, returns a new 4x4 matrix with the result.
1053+ M4x4.rotate = function M4x4_rotate(angle, axis, m, r) {
1054+ //MathUtils_assert(angle.length == 3, "angle.length == 3");
1055+ //MathUtils_assert(axis.length == 3, "axis.length == 3");
1056+ //MathUtils_assert(m.length == 16, "m.length == 16");
1057+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1059+ if (r == undefined)
1060+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1061+ var a0=axis [0], a1=axis [1], a2=axis [2];
1062+ var l = Math.sqrt(a0*a0 + a1*a1 + a2*a2);
1063+ var x = a0, y = a1, z = a2;
1070+ var c = Math.cos(angle);
1072+ var s = Math.sin(angle);
1076+ var xyc1 = x * y * c1;
1077+ var xzc1 = x * z * c1;
1078+ var yzc1 = y * z * c1;
1093+ var t11 = x * x * c1 + c;
1094+ var t21 = xyc1 + zs;
1095+ var t31 = xzc1 - ys;
1096+ var t12 = xyc1 - zs;
1097+ var t22 = y * y * c1 + c;
1098+ var t32 = yzc1 + xs;
1099+ var t13 = xzc1 + ys;
1100+ var t23 = yzc1 - xs;
1101+ var t33 = z * z * c1 + c;
1103+ r[0] = m11 * t11 + m12 * t21 + m13 * t31;
1104+ r[1] = m21 * t11 + m22 * t21 + m23 * t31;
1105+ r[2] = m31 * t11 + m32 * t21 + m33 * t31;
1106+ r[3] = m41 * t11 + m42 * t21 + m43 * t31;
1107+ r[4] = m11 * t12 + m12 * t22 + m13 * t32;
1108+ r[5] = m21 * t12 + m22 * t22 + m23 * t32;
1109+ r[6] = m31 * t12 + m32 * t22 + m33 * t32;
1110+ r[7] = m41 * t12 + m42 * t22 + m43 * t32;
1111+ r[8] = m11 * t13 + m12 * t23 + m13 * t33;
1112+ r[9] = m21 * t13 + m22 * t23 + m23 * t33;
1113+ r[10] = m31 * t13 + m32 * t23 + m33 * t33;
1114+ r[11] = m41 * t13 + m42 * t23 + m43 * t33;
1125+ * Function: M4x4.makeScale3
1127+ * Creates a transformation matrix for scaling by 3 scalar values, one for
1128+ * each of the x, y, and z directions.
1132+ * x - the scale for the x axis
1133+ * y - the scale for the y axis
1134+ * z - the scale for the z axis
1135+ * r - optional 4x4 matrix to store the result in
1139+ * If r is specified, returns r after creating the matrix.
1140+ * Otherwise, returns a new 4x4 matrix with the result.
1142+ M4x4.makeScale3 = function M4x4_makeScale3(x, y, z, r) {
1143+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1145+ if (r == undefined)
1146+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1169+ * Function: M4x4.makeScale1
1171+ * Creates a transformation matrix for a uniform scale by a single scalar value.
1175+ * k - the scale factor
1176+ * r - optional 4x4 matrix to store the result in
1180+ * If r is specified, returns r after creating the matrix.
1181+ * Otherwise, returns a new 4x4 matrix with the result.
1183+ M4x4.makeScale1 = function M4x4_makeScale1(k, r) {
1184+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1186+ return M4x4.makeScale3(k, k, k, r);
1190+ * Function: M4x4.makeScale
1192+ * Creates a transformation matrix for scaling each of the x, y, and z axes by the amount
1193+ * given in the corresponding element of the 3-element vector.
1197+ * v - the 3-element vector containing the scale factors
1198+ * r - optional 4x4 matrix to store the result in
1202+ * If r is specified, returns r after creating the matrix.
1203+ * Otherwise, returns a new 4x4 matrix with the result.
1205+ M4x4.makeScale = function M4x4_makeScale(v, r) {
1206+ //MathUtils_assert(v.length == 3, "v.length == 3");
1207+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1209+ return M4x4.makeScale3(v[0], v[1], v[2], r);
1213+ * Function: M4x4.scale3
1215+ M4x4.scale3 = function M4x4_scale3(x, y, z, m, r) {
1216+ //MathUtils_assert(m.length == 16, "m.length == 16");
1217+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1235+ if (r == undefined)
1236+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1259+ * Function: M4x4.scale1
1261+ M4x4.scale1 = function M4x4_scale1(k, m, r) {
1262+ //MathUtils_assert(m.length == 16, "m.length == 16");
1263+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1281+ if (r == undefined)
1282+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1305+ * Function: M4x4.scale1
1307+ M4x4.scale = function M4x4_scale(v, m, r) {
1308+ //MathUtils_assert(v.length == 3, "v.length == 3");
1309+ //MathUtils_assert(m.length == 16, "m.length == 16");
1310+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1311+ var x = v[0], y = v[1], z = v[2];
1329+ if (r == undefined)
1330+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1354+ * Function: M4x4.makeTranslate3
1356+ M4x4.makeTranslate3 = function M4x4_makeTranslate3(x, y, z, r) {
1357+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1359+ if (r == undefined)
1360+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1383+ * Function: M4x4.makeTranslate1
1385+ M4x4.makeTranslate1 = function M4x4_makeTranslate1 (k, r) {
1386+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1388+ return M4x4.makeTranslate3(k, k, k, r);
1392+ * Function: M4x4.makeTranslate
1394+ M4x4.makeTranslate = function M4x4_makeTranslate (v, r) {
1395+ //MathUtils_assert(v.length == 3, "v.length == 3");
1396+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1398+ return M4x4.makeTranslate3(v[0], v[1], v[2], r);
1402+ * Function: M4x4.translate3Self
1404+ M4x4.translate3Self = function M4x4_translate3Self (x, y, z, m) {
1405+ //MathUtils_assert(m.length == 16, "m.length == 16");
1406+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1407+ m[12] += m[0] * x + m[4] * y + m[8] * z;
1408+ m[13] += m[1] * x + m[5] * y + m[9] * z;
1409+ m[14] += m[2] * x + m[6] * y + m[10] * z;
1410+ m[15] += m[3] * x + m[7] * y + m[11] * z;
1415+ * Function: M4x4.translate3
1417+ M4x4.translate3 = function M4x4_translate3 (x, y, z, m, r) {
1418+ //MathUtils_assert(m.length == 16, "m.length == 16");
1419+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1422+ m[12] += m[0] * x + m[4] * y + m[8] * z;
1423+ m[13] += m[1] * x + m[5] * y + m[9] * z;
1424+ m[14] += m[2] * x + m[6] * y + m[10] * z;
1425+ m[15] += m[3] * x + m[7] * y + m[11] * z;
1429+ if (r == undefined)
1430+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1458+ r[12] = m11 * x + m12 * y + m13 * z + m[12];
1459+ r[13] = m21 * x + m22 * y + m23 * z + m[13];
1460+ r[14] = m31 * x + m32 * y + m33 * z + m[14];
1461+ r[15] = m41 * x + m42 * y + m43 * z + m[15];
1467+ * Function: M4x4.translate1
1469+ M4x4.translate1 = function M4x4_translate1 (k, m, r) {
1470+ //MathUtils_assert(m.length == 16, "m.length == 16");
1471+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1473+ return M4x4.translate3(k, k, k, m, r);
1476+ * Function: M4x4.translateSelf
1478+ M4x4.translateSelf = function M4x4_translateSelf (v, m) {
1479+ //MathUtils_assert(v.length == 3, "v.length == 3");
1480+ //MathUtils_assert(m.length == 16, "m.length == 16");
1481+ var x=v[0], y=v[1], z=v[2];
1482+ m[12] += m[0] * x + m[4] * y + m[8] * z;
1483+ m[13] += m[1] * x + m[5] * y + m[9] * z;
1484+ m[14] += m[2] * x + m[6] * y + m[10] * z;
1485+ m[15] += m[3] * x + m[7] * y + m[11] * z;
1489+ * Function: M4x4.translate
1491+ M4x4.translate = function M4x4_translate (v, m, r) {
1492+ //MathUtils_assert(v.length == 3, "v.length == 3");
1493+ //MathUtils_assert(m.length == 16, "m.length == 16");
1494+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1495+ var x=v[0], y=v[1], z=v[2];
1497+ m[12] += m[0] * x + m[4] * y + m[8] * z;
1498+ m[13] += m[1] * x + m[5] * y + m[9] * z;
1499+ m[14] += m[2] * x + m[6] * y + m[10] * z;
1500+ m[15] += m[3] * x + m[7] * y + m[11] * z;
1504+ if (r == undefined)
1505+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1532+ r[12] = m11 * x + m12 * y + m13 * z + m[12];
1533+ r[13] = m21 * x + m22 * y + m23 * z + m[13];
1534+ r[14] = m31 * x + m32 * y + m33 * z + m[14];
1535+ r[15] = m41 * x + m42 * y + m43 * z + m[15];
1541+ * Function: M4x4.makeLookAt
1543+ M4x4.makeLookAt = function M4x4_makeLookAt (eye, center, up, r) {
1544+ //MathUtils_assert(eye.length == 3, "eye.length == 3");
1545+ //MathUtils_assert(center.length == 3, "center.length == 3");
1546+ //MathUtils_assert(up.length == 3, "up.length == 3");
1547+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1549+ var z = V3.direction(eye, center, V3._temp1);
1550+ var x = V3.normalize(V3.cross(up, z, V3._temp2), V3._temp2);
1551+ var y = V3.normalize(V3.cross(z, x, V3._temp3), V3._temp3);
1553+ var tm1 = M4x4._temp1;
1554+ var tm2 = M4x4._temp2;
1573+ tm2[0] = 1; tm2[1] = 0; tm2[2] = 0; tm2[3] = 0;
1574+ tm2[4] = 0; tm2[5] = 1; tm2[6] = 0; tm2[7] = 0;
1575+ tm2[8] = 0; tm2[9] = 0; tm2[10] = 1; tm2[11] = 0;
1576+ tm2[12] = -eye[0]; tm2[13] = -eye[1]; tm2[14] = -eye[2]; tm2[15] = 1;
1578+ if (r == undefined)
1579+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1580+ return M4x4.mul(tm1, tm2, r);
1584+ * Function: M4x4.transposeSelf
1586+ M4x4.transposeSelf = function M4x4_transposeSelf (m) {
1587+ //MathUtils_assert(m.length == 16, "m.length == 16");
1588+ var tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1589+ tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1590+ tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1591+ tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1592+ tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1593+ tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1597+ * Function: M4x4.transpose
1599+ M4x4.transpose = function M4x4_transpose (m, r) {
1600+ //MathUtils_assert(m.length == 16, "m.length == 16");
1601+ //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1605+ tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1606+ tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1607+ tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1608+ tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1609+ tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1610+ tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1614+ if (r == undefined)
1615+ r = new MJS_FLOAT_ARRAY_TYPE(16);
1617+ r[0] = m[0]; r[1] = m[4]; r[2] = m[8]; r[3] = m[12];
1618+ r[4] = m[1]; r[5] = m[5]; r[6] = m[9]; r[7] = m[13];
1619+ r[8] = m[2]; r[9] = m[6]; r[10] = m[10]; r[11] = m[14];
1620+ r[12] = m[3]; r[13] = m[7]; r[14] = m[11]; r[15] = m[15];
1627+ * Function: M4x4.transformPoint
1629+ M4x4.transformPoint = function M4x4_transformPoint (m, v, r) {
1630+ //MathUtils_assert(m.length == 16, "m.length == 16");
1631+ //MathUtils_assert(v.length == 3, "v.length == 3");
1632+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1633+ if (r == undefined)
1634+ r = new MJS_FLOAT_ARRAY_TYPE(3);
1636+ var v0 = v[0], v1 = v[1], v2 = v[2];
1638+ r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1639+ r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1640+ r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1641+ var w = m[3] * v0 + m[7] * v1 + m[11] * v2 + m[15];
1653+ * Function: M4x4.transformLine
1655+ M4x4.transformLine = function M4x4_transformLine(m, v, r) {
1656+ //MathUtils_assert(m.length == 16, "m.length == 16");
1657+ //MathUtils_assert(v.length == 3, "v.length == 3");
1658+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1659+ if (r == undefined)
1660+ r = new MJS_FLOAT_ARRAY_TYPE(3);
1662+ var v0 = v[0], v1 = v[1], v2 = v[2];
1663+ r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1664+ r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1665+ r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1666+ var w = m[3] * v0 + m[7] * v1 + m[11] * v2;
1679+ * Function: M4x4.transformPointAffine
1681+ M4x4.transformPointAffine = function M4x4_transformPointAffine (m, v, r) {
1682+ //MathUtils_assert(m.length == 16, "m.length == 16");
1683+ //MathUtils_assert(v.length == 3, "v.length == 3");
1684+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1685+ if (r == undefined)
1686+ r = new MJS_FLOAT_ARRAY_TYPE(3);
1688+ var v0 = v[0], v1 = v[1], v2 = v[2];
1690+ r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1691+ r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1692+ r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1698+ * Function: M4x4.transformLineAffine
1700+ M4x4.transformLineAffine = function M4x4_transformLineAffine(m, v, r) {
1701+ //MathUtils_assert(m.length == 16, "m.length == 16");
1702+ //MathUtils_assert(v.length == 3, "v.length == 3");
1703+ //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1704+ if (r == undefined)
1705+ r = new MJS_FLOAT_ARRAY_TYPE(3);
1707+ var v0 = v[0], v1 = v[1], v2 = v[2];
1708+ r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1709+ r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1710+ r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1715+ M4x4.makeBasis = function M4x4_makeBasis(vx,vy,vz) {
1717+ var r = new MJS_FLOAT_ARRAY_TYPE(16);
1743+ toTuple3: V3.toTuple3,
1747+ v3direction: F2(V3.direction),
1748+ v3length: V3.length,
1749+ v3lengthSquared: V3.lengthSquared,
1750+ v3normalize: V3.normalize,
1751+ v3scale: F2(V3.scale),
1753+ v3cross: F2(V3.cross),
1754+ v3mul4x4: F2(V3.mul4x4),
1756+ m4x4identity: M4x4.identity,
1757+ m4x4topLeft3x3: M4x4.topLeft3x3,
1758+ m4x4inverseOrthonormal: M4x4.inverseOrthonormal,
1759+ m4x4inverseTo3x3: M4x4.inverseTo3x3,
1760+ m4x4makeFrustum: F6(M4x4.makeFrustum),
1761+ m4x4makePerspective: F4(M4x4.makePerspective),
1762+ m4x4makeOrtho: F6(M4x4.makeOrtho),
1763+ m4x4makeOrtho2D: F4(M4x4.makeOrtho2D),
1764+ m4x4mul: F2(M4x4.mul),
1765+ m4x4Affine: F2(M4x4.mulAffine),
1766+ m4x4makeRotate: F2(M4x4.makeRotate),
1767+ m4x4rotate: F3(M4x4.rotate),
1768+ m4x4makeScale3: F3(M4x4.makeScale3),
1769+ m4x4makeScale1: M4x4.makeScale1,
1770+ m4x4makeScale: M4x4.makeScale,
1771+ m4x4scale3: F4(M4x4.scale3),
1772+ m4x4scale: F2(M4x4.scale),
1773+ m4x4makeTranslate3: F3(M4x4.makeTranslate3),
1774+ m4x4makeTranslate: M4x4.makeTranslate,
1775+ m4x4translate3: F4(M4x4.translate3),
1776+ m4x4translate: F2(M4x4.translate),
1777+ m4x4makeLookAt: F3(M4x4.makeLookAt),
1778+ m4x4transpose: M4x4.transpose,
1779+ m4x4transformPoint: F2(M4x4.transformPoint),
1780+ m4x4makeBasis: F3(M4x4.makeBasis),