on dbfc352 help sign in
1789 lines 53 kB history raw
2/*
3 * Copyright (c) 2010 Mozilla Corporation
4 * Copyright (c) 2010 Vladimir Vukicevic
5 * Copyright (c) 2013 John Mayer
6 *
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
14 * conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
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.
27 */
29/*
30 * File: mjs
31 *
32 * Vector and Matrix math utilities for JavaScript, optimized for WebGL.
33 * Edited to work with the Elm Programming Language
34 */
36Elm.Native.MJS = {};
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;
43 /*
44 * Constant: MJS_VERSION
45 *
46 * mjs version number aa.bb.cc, encoded as an integer of the form:
47 * 0xaabbcc.
48 */
49 var MJS_VERSION = 0x000000;
51 /*
52 * Constant: MJS_DO_ASSERT
53 *
54 * Enables or disables runtime assertions.
55 *
56 * For potentially more performance, the assert methods can be
57 * commented out in each place where they are called.
58 */
59 var MJS_DO_ASSERT = false;
61 /*
62 * Constant: MJS_FLOAT_ARRAY_TYPE
63 *
64 * The base float array type. By default, WebGLFloatArray.
65 *
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.
70 */
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) {
78 if (!cond) {
79 throw "Assertion failed: " + msg;
80 }
81 }
82 } else {
83 function MathUtils_assert() { }
84 }
86 /*
87 * Class: V3
88 *
89 * Methods for working with 3-element vectors. A vector is represented by a 3-element array.
90 * Any valid JavaScript array type may be used, but if new
91 * vectors are created they are created using the configured MJS_FLOAT_ARRAY_TYPE.
92 */
94 var V3 = { };
96 V3._temp1 = new MJS_FLOAT_ARRAY_TYPE(3);
97 V3._temp2 = new MJS_FLOAT_ARRAY_TYPE(3);
98 V3._temp3 = new MJS_FLOAT_ARRAY_TYPE(3);
100 if (MJS_FLOAT_ARRAY_TYPE == Array) {
101 V3.x = [1.0, 0.0, 0.0];
102 V3.y = [0.0, 1.0, 0.0];
103 V3.z = [0.0, 0.0, 1.0];
105 V3.$ = function V3_$(x, y, z) {
106 return [x, y, z];
107 };
108 } else {
109 V3.x = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0]);
110 V3.y = new MJS_FLOAT_ARRAY_TYPE([0.0, 1.0, 0.0]);
111 V3.z = new MJS_FLOAT_ARRAY_TYPE([0.0, 0.0, 1.0]);
113 /*
114 * Function: V3.$
115 *
116 * Creates a new 3-element vector with the given values.
117 *
118 * Parameters:
119 *
120 * x,y,z - the 3 elements of the new vector.
121 *
122 * Returns:
123 *
124 * A new vector containing with the given argument values.
125 */
127 V3.$ = function V3_$(x, y, z) {
128 return new MJS_FLOAT_ARRAY_TYPE([x, y, z]);
129 };
130 }
132 V3.u = V3.x;
133 V3.v = V3.y;
135 V3.getX = function V3_getX(a) {
136 return a[0];
137 }
138 V3.getY = function V3_getY(a) {
139 return a[1];
140 }
141 V3.getZ = function V3_getZ(a) {
142 return a[2];
143 }
144 V3.setX = function V3_setX(x, a) {
145 return new MJS_FLOAT_ARRAY_TYPE(x, a[1], a[2]);
146 }
147 V3.setY = function V3_setY(y, a) {
148 return new MJS_FLOAT_ARRAY_TYPE(a[0], y, a[2]);
149 }
150 V3.setZ = function V3_setZ(z, a) {
151 return new MJS_FLOAT_ARRAY_TYPE(a[0], a[1], z);
152 }
154 V3.toTuple3 = function V3_toTuple3(a) {
155 return {
156 ctor:"_Tuple3",
157 _0:a[0],
158 _1:a[1],
159 _2:a[2]
160 };
161 };
162 V3.fromTuple3 = function V3_fromTuple3(t) {
163 return new MJS_FLOAT_ARRAY_TYPE([t._0, t._1, t._2]);
164 };
166 V3.toRecord3 = function V3_toRecord3(a) {
167 return {
168 _:{},
169 x:a[0],
170 y:a[1],
171 z:a[2]
172 };
173 };
174 V3.fromRecord3 = function V3_fromRecord3(r) {
175 return new MJS_FLOAT_ARRAY_TYPE([r.x, r.y, r.z]);
176 };
178 /*
179 * Function: V3.add
180 *
181 * Perform r = a + b.
182 *
183 * Parameters:
184 *
185 * a - the first vector operand
186 * b - the second vector operand
187 * r - optional vector to store the result in
188 *
189 * Returns:
190 *
191 * If r is specified, returns r after performing the operation.
192 * Otherwise, returns a new 3-element vector with the result.
193 */
194 V3.add = function V3_add(a, b, r) {
195 //MathUtils_assert(a.length == 3, "a.length == 3");
196 //MathUtils_assert(b.length == 3, "b.length == 3");
197 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
199 if (r == undefined)
200 r = new MJS_FLOAT_ARRAY_TYPE(3);
201 r[0] = a[0] + b[0];
202 r[1] = a[1] + b[1];
203 r[2] = a[2] + b[2];
204 return r;
205 };
207 /*
208 * Function: V3.sub
209 *
210 * Perform
211 * r = a - b.
212 *
213 * Parameters:
214 *
215 * a - the first vector operand
216 * b - the second vector operand
217 * r - optional vector to store the result in
218 *
219 * Returns:
220 *
221 * If r is specified, returns r after performing the operation.
222 * Otherwise, returns a new 3-element vector with the result.
223 */
224 V3.sub = function V3_sub(a, b, r) {
225 //MathUtils_assert(a.length == 3, "a.length == 3");
226 //MathUtils_assert(b.length == 3, "b.length == 3");
227 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
229 if (r == undefined)
230 r = new MJS_FLOAT_ARRAY_TYPE(3);
231 r[0] = a[0] - b[0];
232 r[1] = a[1] - b[1];
233 r[2] = a[2] - b[2];
234 return r;
235 };
237 /*
238 * Function: V3.neg
239 *
240 * Perform
241 * r = - a.
242 *
243 * Parameters:
244 *
245 * a - the vector operand
246 * r - optional vector to store the result in
247 *
248 * Returns:
249 *
250 * If r is specified, returns r after performing the operation.
251 * Otherwise, returns a new 3-element vector with the result.
252 */
253 V3.neg = function V3_neg(a, r) {
254 //MathUtils_assert(a.length == 3, "a.length == 3");
255 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
257 if (r == undefined)
258 r = new MJS_FLOAT_ARRAY_TYPE(3);
259 r[0] = - a[0];
260 r[1] = - a[1];
261 r[2] = - a[2];
262 return r;
263 };
265 /*
266 * Function: V3.direction
267 *
268 * Perform
269 * r = (a - b) / |a - b|. The result is the normalized
270 * direction from a to b.
271 *
272 * Parameters:
273 *
274 * a - the first vector operand
275 * b - the second vector operand
276 * r - optional vector to store the result in
277 *
278 * Returns:
279 *
280 * If r is specified, returns r after performing the operation.
281 * Otherwise, returns a new 3-element vector with the result.
282 */
283 V3.direction = function V3_direction(a, b, r) {
284 //MathUtils_assert(a.length == 3, "a.length == 3");
285 //MathUtils_assert(b.length == 3, "b.length == 3");
286 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
288 if (r == undefined)
289 r = new MJS_FLOAT_ARRAY_TYPE(3);
290 return V3.normalize(V3.sub(a, b, r), r);
291 };
293 /*
294 * Function: V3.length
295 *
296 * Perform r = |a|.
297 *
298 * Parameters:
299 *
300 * a - the vector operand
301 *
302 * Returns:
303 *
304 * The length of the given vector.
305 */
306 V3.length = function V3_length(a) {
307 //MathUtils_assert(a.length == 3, "a.length == 3");
309 return Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
310 };
312 /*
313 * Function: V3.lengthSquard
314 *
315 * Perform r = |a|*|a|.
316 *
317 * Parameters:
318 *
319 * a - the vector operand
320 *
321 * Returns:
322 *
323 * The square of the length of the given vector.
324 */
325 V3.lengthSquared = function V3_lengthSquared(a) {
326 //MathUtils_assert(a.length == 3, "a.length == 3");
328 return a[0]*a[0] + a[1]*a[1] + a[2]*a[2];
329 };
331 V3.distance = function V3_distance(a, b) {
332 var dx = a[0] - b[0];
333 var dy = a[1] - b[1];
334 var dz = a[2] - b[2];
335 return Math.sqrt(dx * dx + dy * dy + dz * dz);
336 };
338 V3.distanceSquared = function V3_distanceSquared(a) {
339 var dx = a[0] - b[0];
340 var dy = a[1] - b[1];
341 var dz = a[2] - b[2];
342 return dx * dx + dy * dy + dz * dz;
343 };
345 /*
346 * Function: V3.normalize
347 *
348 * Perform r = a / |a|.
349 *
350 * Parameters:
351 *
352 * a - the vector operand
353 * r - optional vector to store the result in
354 *
355 * Returns:
356 *
357 * If r is specified, returns r after performing the operation.
358 * Otherwise, returns a new 3-element vector with the result.
359 */
360 V3.normalize = function V3_normalize(a, r) {
361 //MathUtils_assert(a.length == 3, "a.length == 3");
362 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
364 if (r == undefined)
365 r = new MJS_FLOAT_ARRAY_TYPE(3);
366 var im = 1.0 / V3.length(a);
367 r[0] = a[0] * im;
368 r[1] = a[1] * im;
369 r[2] = a[2] * im;
370 return r;
371 };
373 /*
374 * Function: V3.scale
375 *
376 * Perform r = a * k.
377 *
378 * Parameters:
379 *
380 * a - the vector operand
381 * k - a scalar value
382 * r - optional vector to store the result in
383 *
384 * Returns:
385 *
386 * If r is specified, returns r after performing the operation.
387 * Otherwise, returns a new 3-element vector with the result.
388 */
389 V3.scale = function V3_scale(a, k, r) {
390 //MathUtils_assert(a.length == 3, "a.length == 3");
391 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
393 if (r == undefined)
394 r = new MJS_FLOAT_ARRAY_TYPE(3);
395 r[0] = a[0] * k;
396 r[1] = a[1] * k;
397 r[2] = a[2] * k;
398 return r;
399 };
401 /*
402 * Function: V3.dot
403 *
404 * Perform
405 * r = dot(a, b).
406 *
407 * Parameters:
408 *
409 * a - the first vector operand
410 * b - the second vector operand
411 *
412 * Returns:
413 *
414 * The dot product of a and b.
415 */
416 V3.dot = function V3_dot(a, b) {
417 //MathUtils_assert(a.length == 3, "a.length == 3");
418 //MathUtils_assert(b.length == 3, "b.length == 3");
420 return a[0] * b[0] +
421 a[1] * b[1] +
422 a[2] * b[2];
423 };
425 /*
426 * Function: V3.cross
427 *
428 * Perform r = a x b.
429 *
430 * Parameters:
431 *
432 * a - the first vector operand
433 * b - the second vector operand
434 * r - optional vector to store the result in
435 *
436 * Returns:
437 *
438 * If r is specified, returns r after performing the operation.
439 * Otherwise, returns a new 3-element vector with the result.
440 */
441 V3.cross = function V3_cross(a, b, r) {
442 //MathUtils_assert(a.length == 3, "a.length == 3");
443 //MathUtils_assert(b.length == 3, "b.length == 3");
444 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
446 if (r == undefined)
447 r = new MJS_FLOAT_ARRAY_TYPE(3);
448 r[0] = a[1]*b[2] - a[2]*b[1];
449 r[1] = a[2]*b[0] - a[0]*b[2];
450 r[2] = a[0]*b[1] - a[1]*b[0];
451 return r;
452 };
454 /*
455 * Function: V3.mul4x4
456 *
457 * Perform
458 * r = m * v.
459 *
460 * Parameters:
461 *
462 * m - the 4x4 matrix operand
463 * v - the 3-element vector operand
464 * r - optional vector to store the result in
465 *
466 * Returns:
467 *
468 * If r is specified, returns r after performing the operation.
469 * Otherwise, returns a new 3-element vector with the result.
470 * The 4-element result vector is divided by the w component
471 * and returned as a 3-element vector.
472 */
473 V3.mul4x4 = function V3_mul4x4(m, v, r) {
474 //MathUtils_assert(m.length == 16, "m.length == 16");
475 //MathUtils_assert(v.length == 3, "v.length == 3");
476 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
478 var w;
479 var tmp = V3._temp1;
480 if (r == undefined)
481 r = new MJS_FLOAT_ARRAY_TYPE(3);
482 tmp[0] = m[ 3];
483 tmp[1] = m[ 7];
484 tmp[2] = m[11];
485 w = V3.dot(v, tmp) + m[15];
486 tmp[0] = m[ 0];
487 tmp[1] = m[ 4];
488 tmp[2] = m[ 8];
489 r[0] = (V3.dot(v, tmp) + m[12])/w;
490 tmp[0] = m[ 1];
491 tmp[1] = m[ 5];
492 tmp[2] = m[ 9];
493 r[1] = (V3.dot(v, tmp) + m[13])/w;
494 tmp[0] = m[ 2];
495 tmp[1] = m[ 6];
496 tmp[2] = m[10];
497 r[2] = (V3.dot(v, tmp) + m[14])/w;
498 return r;
499 };
501 /*
502 * Class: M4x4
503 *
504 * Methods for working with 4x4 matrices. A matrix is represented by a 16-element array
505 * in column-major order. Any valid JavaScript array type may be used, but if new
506 * matrices are created they are created using the configured MJS_FLOAT_ARRAY_TYPE.
507 */
509 var M4x4 = { };
511 M4x4._temp1 = new MJS_FLOAT_ARRAY_TYPE(16);
512 M4x4._temp2 = new MJS_FLOAT_ARRAY_TYPE(16);
514 if (MJS_FLOAT_ARRAY_TYPE == Array) {
515 M4x4.I = [1.0, 0.0, 0.0, 0.0,
516 0.0, 1.0, 0.0, 0.0,
517 0.0, 0.0, 1.0, 0.0,
518 0.0, 0.0, 0.0, 1.0];
520 M4x4.$ = function M4x4_$(m00, m01, m02, m03,
521 m04, m05, m06, m07,
522 m08, m09, m10, m11,
523 m12, m13, m14, m15)
524 {
525 return [m00, m01, m02, m03,
526 m04, m05, m06, m07,
527 m08, m09, m10, m11,
528 m12, m13, m14, m15];
529 };
530 } else {
531 M4x4.I = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0, 0.0,
532 0.0, 1.0, 0.0, 0.0,
533 0.0, 0.0, 1.0, 0.0,
534 0.0, 0.0, 0.0, 1.0]);
536 /*
537 * Function: M4x4.$
538 *
539 * Creates a new 4x4 matrix with the given values.
540 *
541 * Parameters:
542 *
543 * m00..m15 - the 16 elements of the new matrix.
544 *
545 * Returns:
546 *
547 * A new matrix filled with the given argument values.
548 */
549 M4x4.$ = function M4x4_$(m00, m01, m02, m03,
550 m04, m05, m06, m07,
551 m08, m09, m10, m11,
552 m12, m13, m14, m15)
553 {
554 return new MJS_FLOAT_ARRAY_TYPE([m00, m01, m02, m03,
555 m04, m05, m06, m07,
556 m08, m09, m10, m11,
557 m12, m13, m14, m15]);
558 };
559 }
561 M4x4.identity = M4x4.I;
563 /*
564 * Function: M4x4.topLeft3x3
565 *
566 * Return the top left 3x3 matrix from the given 4x4 matrix m.
567 *
568 * Parameters:
569 *
570 * m - the matrix
571 * r - optional 3x3 matrix to store the result in
572 *
573 * Returns:
574 *
575 * If r is specified, returns r after performing the operation.
576 * Otherwise, returns a new 3x3 matrix with the result.
577 */
578 M4x4.topLeft3x3 = function M4x4_topLeft3x3(m, r) {
579 //MathUtils_assert(m.length == 16, "m.length == 16");
580 //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
582 if (r == undefined)
583 r = new MJS_FLOAT_ARRAY_TYPE(9);
584 r[0] = m[0]; r[1] = m[1]; r[2] = m[2];
585 r[3] = m[4]; r[4] = m[5]; r[5] = m[6];
586 r[6] = m[8]; r[7] = m[9]; r[8] = m[10];
587 return r;
588 };
590 /*
591 * Function: M4x4.inverseOrthonormal
592 *
593 * Computes the inverse of the given matrix m, assuming that
594 * the matrix is orthonormal.
595 *
596 * Parameters:
597 *
598 * m - the matrix
599 * r - optional 4x4 matrix to store the result in
600 *
601 * Returns:
602 *
603 * If r is specified, returns r after performing the operation.
604 * Otherwise, returns a new 4x4 matrix with the result.
605 */
606 M4x4.inverseOrthonormal = function M4x4_inverseOrthonormal(m, r) {
607 //MathUtils_assert(m.length == 16, "m.length == 16");
608 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
609 //MathUtils_assert(m != r, "m != r");
611 if (r == undefined)
612 r = new MJS_FLOAT_ARRAY_TYPE(16);
613 M4x4.transpose(m, r);
614 var t = [m[12], m[13], m[14]];
615 r[3] = r[7] = r[11] = 0;
616 r[12] = -V3.dot([r[0], r[4], r[8]], t);
617 r[13] = -V3.dot([r[1], r[5], r[9]], t);
618 r[14] = -V3.dot([r[2], r[6], r[10]], t);
619 return r;
620 };
622 /*
623 * Function: M4x4.inverseTo3x3
624 *
625 * Computes the inverse of the given matrix m, but calculates
626 * only the top left 3x3 values of the result.
627 *
628 * Parameters:
629 *
630 * m - the matrix
631 * r - optional 3x3 matrix to store the result in
632 *
633 * Returns:
634 *
635 * If r is specified, returns r after performing the operation.
636 * Otherwise, returns a new 3x3 matrix with the result.
637 */
638 M4x4.inverseTo3x3 = function M4x4_inverseTo3x3(m, r) {
639 //MathUtils_assert(m.length == 16, "m.length == 16");
640 //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
642 if (r == undefined)
643 r = new MJS_FLOAT_ARRAY_TYPE(9);
645 var a11 = m[10]*m[5]-m[6]*m[9],
646 a21 = -m[10]*m[1]+m[2]*m[9],
647 a31 = m[6]*m[1]-m[2]*m[5],
648 a12 = -m[10]*m[4]+m[6]*m[8],
649 a22 = m[10]*m[0]-m[2]*m[8],
650 a32 = -m[6]*m[0]+m[2]*m[4],
651 a13 = m[9]*m[4]-m[5]*m[8],
652 a23 = -m[9]*m[0]+m[1]*m[8],
653 a33 = m[5]*m[0]-m[1]*m[4];
654 var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13);
655 if (det == 0) // no inverse
656 throw "matrix not invertible";
657 var idet = 1.0 / det;
659 r[0] = idet*a11;
660 r[1] = idet*a21;
661 r[2] = idet*a31;
662 r[3] = idet*a12;
663 r[4] = idet*a22;
664 r[5] = idet*a32;
665 r[6] = idet*a13;
666 r[7] = idet*a23;
667 r[8] = idet*a33;
669 return r;
670 };
672 /*
673 * Function: M4x4.makeFrustum
674 *
675 * Creates a matrix for a projection frustum with the given parameters.
676 *
677 * Parameters:
678 *
679 * left - the left coordinate of the frustum
680 * right- the right coordinate of the frustum
681 * bottom - the bottom coordinate of the frustum
682 * top - the top coordinate of the frustum
683 * znear - the near z distance of the frustum
684 * zfar - the far z distance of the frustum
685 * r - optional 4x4 matrix to store the result in
686 *
687 * Returns:
688 *
689 * If r is specified, returns r after creating the projection matrix.
690 * Otherwise, returns a new 4x4 matrix.
691 */
692 M4x4.makeFrustum = function M4x4_makeFrustum(left, right, bottom, top, znear, zfar, r) {
693 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
695 if (r == undefined)
696 r = new MJS_FLOAT_ARRAY_TYPE(16);
698 var X = 2*znear/(right-left);
699 var Y = 2*znear/(top-bottom);
700 var A = (right+left)/(right-left);
701 var B = (top+bottom)/(top-bottom);
702 var C = -(zfar+znear)/(zfar-znear);
703 var D = -2*zfar*znear/(zfar-znear);
705 r[0] = 2*znear/(right-left);
706 r[1] = 0;
707 r[2] = 0;
708 r[3] = 0;
709 r[4] = 0;
710 r[5] = 2*znear/(top-bottom);
711 r[6] = 0;
712 r[7] = 0;
713 r[8] = (right+left)/(right-left);
714 r[9] = (top+bottom)/(top-bottom);
715 r[10] = -(zfar+znear)/(zfar-znear);
716 r[11] = -1;
717 r[12] = 0;
718 r[13] = 0;
719 r[14] = -2*zfar*znear/(zfar-znear);
720 r[15] = 0;
722 return r;
723 };
725 /*
726 * Function: M4x4.makePerspective
727 *
728 * Creates a matrix for a perspective projection with the given parameters.
729 *
730 * Parameters:
731 *
732 * fovy - field of view in the y axis, in degrees
733 * aspect - aspect ratio
734 * znear - the near z distance of the projection
735 * zfar - the far z distance of the projection
736 * r - optional 4x4 matrix to store the result in
737 *
738 * Returns:
739 *
740 * If r is specified, returns r after creating the projection matrix.
741 * Otherwise, returns a new 4x4 matrix.
742 */
743 M4x4.makePerspective = function M4x4_makePerspective (fovy, aspect, znear, zfar, r) {
744 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
746 var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
747 var ymin = -ymax;
748 var xmin = ymin * aspect;
749 var xmax = ymax * aspect;
751 return M4x4.makeFrustum(xmin, xmax, ymin, ymax, znear, zfar, r);
752 };
754 /*
755 * Function: M4x4.makeOrtho
756 *
757 * Creates a matrix for an orthogonal frustum projection with the given parameters.
758 *
759 * Parameters:
760 *
761 * left - the left coordinate of the frustum
762 * right- the right coordinate of the frustum
763 * bottom - the bottom coordinate of the frustum
764 * top - the top coordinate of the frustum
765 * znear - the near z distance of the frustum
766 * zfar - the far z distance of the frustum
767 * r - optional 4x4 matrix to store the result in
768 *
769 * Returns:
770 *
771 * If r is specified, returns r after creating the projection matrix.
772 * Otherwise, returns a new 4x4 matrix.
773 */
774 M4x4.makeOrtho = function M4x4_makeOrtho (left, right, bottom, top, znear, zfar, r) {
775 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
777 if (r == undefined)
778 r = new MJS_FLOAT_ARRAY_TYPE(16);
780 var tX = -(right+left)/(right-left);
781 var tY = -(top+bottom)/(top-bottom);
782 var tZ = -(zfar+znear)/(zfar-znear);
783 var X = 2 / (right-left);
784 var Y = 2 / (top-bottom);
785 var Z = -2 / (zfar-znear);
787 r[0] = 2 / (right-left);
788 r[1] = 0;
789 r[2] = 0;
790 r[3] = 0;
791 r[4] = 0;
792 r[5] = 2 / (top-bottom);
793 r[6] = 0;
794 r[7] = 0;
795 r[8] = 0;
796 r[9] = 0;
797 r[10] = -2 / (zfar-znear);
798 r[11] = 0;
799 r[12] = -(right+left)/(right-left);
800 r[13] = -(top+bottom)/(top-bottom);
801 r[14] = -(zfar+znear)/(zfar-znear);
802 r[15] = 1;
804 return r;
805 };
807 /*
808 * Function: M4x4.makeOrtho2D
809 *
810 * Creates a matrix for a 2D orthogonal frustum projection with the given parameters.
811 * znear and zfar are assumed to be -1 and 1, respectively.
812 *
813 * Parameters:
814 *
815 * left - the left coordinate of the frustum
816 * right- the right coordinate of the frustum
817 * bottom - the bottom coordinate of the frustum
818 * top - the top coordinate of the frustum
819 * r - optional 4x4 matrix to store the result in
820 *
821 * Returns:
822 *
823 * If r is specified, returns r after creating the projection matrix.
824 * Otherwise, returns a new 4x4 matrix.
825 */
826 M4x4.makeOrtho2D = function M4x4_makeOrtho2D (left, right, bottom, top, r) {
827 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
829 return M4x4.makeOrtho(left, right, bottom, top, -1, 1, r);
830 };
832 /*
833 * Function: M4x4.mul
834 *
835 * Performs r = a * b.
836 *
837 * Parameters:
838 *
839 * a - the first matrix operand
840 * b - the second matrix operand
841 * r - optional 4x4 matrix to store the result in
842 *
843 * Returns:
844 *
845 * If r is specified, returns r after performing the operation.
846 * Otherwise, returns a new 4x4 matrix with the result.
847 */
848 M4x4.mul = function M4x4_mul(a, b, r) {
849 //MathUtils_assert(a.length == 16, "a.length == 16");
850 //MathUtils_assert(b.length == 16, "b.length == 16");
851 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
852 //MathUtils_assert(a != r && b != r, "a != r && b != r");
854 if (r == undefined)
855 r = new MJS_FLOAT_ARRAY_TYPE(16);
857 var a11 = a[0];
858 var a21 = a[1];
859 var a31 = a[2];
860 var a41 = a[3];
861 var a12 = a[4];
862 var a22 = a[5];
863 var a32 = a[6];
864 var a42 = a[7];
865 var a13 = a[8];
866 var a23 = a[9];
867 var a33 = a[10];
868 var a43 = a[11];
869 var a14 = a[12];
870 var a24 = a[13];
871 var a34 = a[14];
872 var a44 = a[15];
874 var b11 = b[0];
875 var b21 = b[1];
876 var b31 = b[2];
877 var b41 = b[3];
878 var b12 = b[4];
879 var b22 = b[5];
880 var b32 = b[6];
881 var b42 = b[7];
882 var b13 = b[8];
883 var b23 = b[9];
884 var b33 = b[10];
885 var b43 = b[11];
886 var b14 = b[12];
887 var b24 = b[13];
888 var b34 = b[14];
889 var b44 = b[15];
891 r[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
892 r[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
893 r[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
894 r[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
895 r[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
896 r[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
897 r[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
898 r[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
899 r[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
900 r[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
901 r[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
902 r[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
903 r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
904 r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
905 r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
906 r[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
908 return r;
909 };
911 /*
912 * Function: M4x4.mulAffine
913 *
914 * Performs r = a * b, assuming a and b are affine (elements 3,7,11,15 = 0,0,0,1)
915 *
916 * Parameters:
917 *
918 * a - the first matrix operand
919 * b - the second matrix operand
920 * r - optional 4x4 matrix to store the result in
921 *
922 * Returns:
923 *
924 * If r is specified, returns r after performing the operation.
925 * Otherwise, returns a new 4x4 matrix with the result.
926 */
927 M4x4.mulAffine = function M4x4_mulAffine(a, b, r) {
928 //MathUtils_assert(a.length == 16, "a.length == 16");
929 //MathUtils_assert(b.length == 16, "b.length == 16");
930 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
931 //MathUtils_assert(a != r && b != r, "a != r && b != r");
933 if (r == undefined)
934 r = new MJS_FLOAT_ARRAY_TYPE(16);
935 var a11 = a[0];
936 var a21 = a[1];
937 var a31 = a[2];
938 var a12 = a[4];
939 var a22 = a[5];
940 var a32 = a[6];
941 var a13 = a[8];
942 var a23 = a[9];
943 var a33 = a[10];
944 var a14 = a[12];
945 var a24 = a[13];
946 var a34 = a[14];
948 var b11 = b[0];
949 var b21 = b[1];
950 var b31 = b[2];
951 var b12 = b[4];
952 var b22 = b[5];
953 var b32 = b[6];
954 var b13 = b[8];
955 var b23 = b[9];
956 var b33 = b[10];
957 var b14 = b[12];
958 var b24 = b[13];
959 var b34 = b[14];
961 r[0] = a11 * b11 + a12 * b21 + a13 * b31;
962 r[1] = a21 * b11 + a22 * b21 + a23 * b31;
963 r[2] = a31 * b11 + a32 * b21 + a33 * b31;
964 r[3] = 0;
965 r[4] = a11 * b12 + a12 * b22 + a13 * b32;
966 r[5] = a21 * b12 + a22 * b22 + a23 * b32;
967 r[6] = a31 * b12 + a32 * b22 + a33 * b32;
968 r[7] = 0;
969 r[8] = a11 * b13 + a12 * b23 + a13 * b33;
970 r[9] = a21 * b13 + a22 * b23 + a23 * b33;
971 r[10] = a31 * b13 + a32 * b23 + a33 * b33;
972 r[11] = 0;
973 r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14;
974 r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24;
975 r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34;
976 r[15] = 1;
978 return r;
979 };
981 /*
982 * Function: M4x4.makeRotate
983 *
984 * Creates a transformation matrix for rotation by angle radians about the 3-element vector axis.
985 *
986 * Parameters:
987 *
988 * angle - the angle of rotation, in radians
989 * axis - the axis around which the rotation is performed, a 3-element vector
990 * r - optional 4x4 matrix to store the result in
991 *
992 * Returns:
993 *
994 * If r is specified, returns r after creating the matrix.
995 * Otherwise, returns a new 4x4 matrix with the result.
996 */
997 M4x4.makeRotate = function M4x4_makeRotate(angle, axis, r) {
998 //MathUtils_assert(angle.length == 3, "angle.length == 3");
999 //MathUtils_assert(axis.length == 3, "axis.length == 3");
1000 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1002 if (r == undefined)
1003 r = new MJS_FLOAT_ARRAY_TYPE(16);
1005 axis = V3.normalize(axis, V3._temp1);
1006 var x = axis[0], y = axis[1], z = axis[2];
1007 var c = Math.cos(angle);
1008 var c1 = 1-c;
1009 var s = Math.sin(angle);
1011 r[0] = x*x*c1+c;
1012 r[1] = y*x*c1+z*s;
1013 r[2] = z*x*c1-y*s;
1014 r[3] = 0;
1015 r[4] = x*y*c1-z*s;
1016 r[5] = y*y*c1+c;
1017 r[6] = y*z*c1+x*s;
1018 r[7] = 0;
1019 r[8] = x*z*c1+y*s;
1020 r[9] = y*z*c1-x*s;
1021 r[10] = z*z*c1+c;
1022 r[11] = 0;
1023 r[12] = 0;
1024 r[13] = 0;
1025 r[14] = 0;
1026 r[15] = 1;
1028 return r;
1029 };
1031 /*
1032 * Function: M4x4.rotate
1034 * Concatenates a rotation of angle radians about the axis to the give matrix m.
1036 * Parameters:
1038 * angle - the angle of rotation, in radians
1039 * axis - the axis around which the rotation is performed, a 3-element vector
1040 * m - the matrix to concatenate the rotation to
1041 * r - optional 4x4 matrix to store the result in
1043 * Returns:
1045 * If r is specified, returns r after performing the operation.
1046 * Otherwise, returns a new 4x4 matrix with the result.
1047 */
1048 M4x4.rotate = function M4x4_rotate(angle, axis, m, r) {
1049 //MathUtils_assert(angle.length == 3, "angle.length == 3");
1050 //MathUtils_assert(axis.length == 3, "axis.length == 3");
1051 //MathUtils_assert(m.length == 16, "m.length == 16");
1052 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1054 if (r == undefined)
1055 r = new MJS_FLOAT_ARRAY_TYPE(16);
1056 var a0=axis [0], a1=axis [1], a2=axis [2];
1057 var l = Math.sqrt(a0*a0 + a1*a1 + a2*a2);
1058 var x = a0, y = a1, z = a2;
1059 if (l != 1.0) {
1060 var im = 1.0 / l;
1061 x *= im;
1062 y *= im;
1063 z *= im;
1065 var c = Math.cos(angle);
1066 var c1 = 1-c;
1067 var s = Math.sin(angle);
1068 var xs = x*s;
1069 var ys = y*s;
1070 var zs = z*s;
1071 var xyc1 = x * y * c1;
1072 var xzc1 = x * z * c1;
1073 var yzc1 = y * z * c1;
1075 var m11 = m[0];
1076 var m21 = m[1];
1077 var m31 = m[2];
1078 var m41 = m[3];
1079 var m12 = m[4];
1080 var m22 = m[5];
1081 var m32 = m[6];
1082 var m42 = m[7];
1083 var m13 = m[8];
1084 var m23 = m[9];
1085 var m33 = m[10];
1086 var m43 = m[11];
1088 var t11 = x * x * c1 + c;
1089 var t21 = xyc1 + zs;
1090 var t31 = xzc1 - ys;
1091 var t12 = xyc1 - zs;
1092 var t22 = y * y * c1 + c;
1093 var t32 = yzc1 + xs;
1094 var t13 = xzc1 + ys;
1095 var t23 = yzc1 - xs;
1096 var t33 = z * z * c1 + c;
1098 r[0] = m11 * t11 + m12 * t21 + m13 * t31;
1099 r[1] = m21 * t11 + m22 * t21 + m23 * t31;
1100 r[2] = m31 * t11 + m32 * t21 + m33 * t31;
1101 r[3] = m41 * t11 + m42 * t21 + m43 * t31;
1102 r[4] = m11 * t12 + m12 * t22 + m13 * t32;
1103 r[5] = m21 * t12 + m22 * t22 + m23 * t32;
1104 r[6] = m31 * t12 + m32 * t22 + m33 * t32;
1105 r[7] = m41 * t12 + m42 * t22 + m43 * t32;
1106 r[8] = m11 * t13 + m12 * t23 + m13 * t33;
1107 r[9] = m21 * t13 + m22 * t23 + m23 * t33;
1108 r[10] = m31 * t13 + m32 * t23 + m33 * t33;
1109 r[11] = m41 * t13 + m42 * t23 + m43 * t33;
1110 if (r != m) {
1111 r[12] = m[12];
1112 r[13] = m[13];
1113 r[14] = m[14];
1114 r[15] = m[15];
1116 return r;
1117 };
1119 /*
1120 * Function: M4x4.makeScale3
1122 * Creates a transformation matrix for scaling by 3 scalar values, one for
1123 * each of the x, y, and z directions.
1125 * Parameters:
1127 * x - the scale for the x axis
1128 * y - the scale for the y axis
1129 * z - the scale for the z axis
1130 * r - optional 4x4 matrix to store the result in
1132 * Returns:
1134 * If r is specified, returns r after creating the matrix.
1135 * Otherwise, returns a new 4x4 matrix with the result.
1136 */
1137 M4x4.makeScale3 = function M4x4_makeScale3(x, y, z, r) {
1138 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1140 if (r == undefined)
1141 r = new MJS_FLOAT_ARRAY_TYPE(16);
1143 r[0] = x;
1144 r[1] = 0;
1145 r[2] = 0;
1146 r[3] = 0;
1147 r[4] = 0;
1148 r[5] = y;
1149 r[6] = 0;
1150 r[7] = 0;
1151 r[8] = 0;
1152 r[9] = 0;
1153 r[10] = z;
1154 r[11] = 0;
1155 r[12] = 0;
1156 r[13] = 0;
1157 r[14] = 0;
1158 r[15] = 1;
1160 return r;
1161 };
1163 /*
1164 * Function: M4x4.makeScale1
1166 * Creates a transformation matrix for a uniform scale by a single scalar value.
1168 * Parameters:
1170 * k - the scale factor
1171 * r - optional 4x4 matrix to store the result in
1173 * Returns:
1175 * If r is specified, returns r after creating the matrix.
1176 * Otherwise, returns a new 4x4 matrix with the result.
1177 */
1178 M4x4.makeScale1 = function M4x4_makeScale1(k, r) {
1179 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1181 return M4x4.makeScale3(k, k, k, r);
1182 };
1184 /*
1185 * Function: M4x4.makeScale
1187 * Creates a transformation matrix for scaling each of the x, y, and z axes by the amount
1188 * given in the corresponding element of the 3-element vector.
1190 * Parameters:
1192 * v - the 3-element vector containing the scale factors
1193 * r - optional 4x4 matrix to store the result in
1195 * Returns:
1197 * If r is specified, returns r after creating the matrix.
1198 * Otherwise, returns a new 4x4 matrix with the result.
1199 */
1200 M4x4.makeScale = function M4x4_makeScale(v, r) {
1201 //MathUtils_assert(v.length == 3, "v.length == 3");
1202 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1204 return M4x4.makeScale3(v[0], v[1], v[2], r);
1205 };
1207 /*
1208 * Function: M4x4.scale3
1209 */
1210 M4x4.scale3 = function M4x4_scale3(x, y, z, m, r) {
1211 //MathUtils_assert(m.length == 16, "m.length == 16");
1212 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1214 if (r == m) {
1215 m[0] *= x;
1216 m[1] *= x;
1217 m[2] *= x;
1218 m[3] *= x;
1219 m[4] *= y;
1220 m[5] *= y;
1221 m[6] *= y;
1222 m[7] *= y;
1223 m[8] *= z;
1224 m[9] *= z;
1225 m[10] *= z;
1226 m[11] *= z;
1227 return m;
1230 if (r == undefined)
1231 r = new MJS_FLOAT_ARRAY_TYPE(16);
1233 r[0] = m[0] * x;
1234 r[1] = m[1] * x;
1235 r[2] = m[2] * x;
1236 r[3] = m[3] * x;
1237 r[4] = m[4] * y;
1238 r[5] = m[5] * y;
1239 r[6] = m[6] * y;
1240 r[7] = m[7] * y;
1241 r[8] = m[8] * z;
1242 r[9] = m[9] * z;
1243 r[10] = m[10] * z;
1244 r[11] = m[11] * z;
1245 r[12] = m[12];
1246 r[13] = m[13];
1247 r[14] = m[14];
1248 r[15] = m[15];
1250 return r;
1251 };
1253 /*
1254 * Function: M4x4.scale1
1255 */
1256 M4x4.scale1 = function M4x4_scale1(k, m, r) {
1257 //MathUtils_assert(m.length == 16, "m.length == 16");
1258 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1259 if (r == m) {
1260 m[0] *= k;
1261 m[1] *= k;
1262 m[2] *= k;
1263 m[3] *= k;
1264 m[4] *= k;
1265 m[5] *= k;
1266 m[6] *= k;
1267 m[7] *= k;
1268 m[8] *= k;
1269 m[9] *= k;
1270 m[10] *= k;
1271 m[11] *= k;
1272 return m;
1276 if (r == undefined)
1277 r = new MJS_FLOAT_ARRAY_TYPE(16);
1279 r[0] = m[0] * k;
1280 r[1] = m[1] * k;
1281 r[2] = m[2] * k;
1282 r[3] = m[3] * k;
1283 r[4] = m[4] * k;
1284 r[5] = m[5] * k;
1285 r[6] = m[6] * k;
1286 r[7] = m[7] * k;
1287 r[8] = m[8] * k;
1288 r[9] = m[9] * k;
1289 r[10] = m[10] * k;
1290 r[11] = m[11] * k;
1291 r[12] = m[12];
1292 r[13] = m[13];
1293 r[14] = m[14];
1294 r[15] = m[15];
1296 return r;
1297 };
1299 /*
1300 * Function: M4x4.scale1
1301 */
1302 M4x4.scale = function M4x4_scale(v, m, r) {
1303 //MathUtils_assert(v.length == 3, "v.length == 3");
1304 //MathUtils_assert(m.length == 16, "m.length == 16");
1305 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1306 var x = v[0], y = v[1], z = v[2];
1308 if (r == m) {
1309 m[0] *= x;
1310 m[1] *= x;
1311 m[2] *= x;
1312 m[3] *= x;
1313 m[4] *= y;
1314 m[5] *= y;
1315 m[6] *= y;
1316 m[7] *= y;
1317 m[8] *= z;
1318 m[9] *= z;
1319 m[10] *= z;
1320 m[11] *= z;
1321 return m;
1324 if (r == undefined)
1325 r = new MJS_FLOAT_ARRAY_TYPE(16);
1328 r[0] = m[0] * x;
1329 r[1] = m[1] * x;
1330 r[2] = m[2] * x;
1331 r[3] = m[3] * x;
1332 r[4] = m[4] * y;
1333 r[5] = m[5] * y;
1334 r[6] = m[6] * y;
1335 r[7] = m[7] * y;
1336 r[8] = m[8] * z;
1337 r[9] = m[9] * z;
1338 r[10] = m[10] * z;
1339 r[11] = m[11] * z;
1340 r[12] = m[12];
1341 r[13] = m[13];
1342 r[14] = m[14];
1343 r[15] = m[15];
1345 return r;
1346 };
1348 /*
1349 * Function: M4x4.makeTranslate3
1350 */
1351 M4x4.makeTranslate3 = function M4x4_makeTranslate3(x, y, z, r) {
1352 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1354 if (r == undefined)
1355 r = new MJS_FLOAT_ARRAY_TYPE(16);
1357 r[0] = 1;
1358 r[1] = 0;
1359 r[2] = 0;
1360 r[3] = 0;
1361 r[4] = 0;
1362 r[5] = 1;
1363 r[6] = 0;
1364 r[7] = 0;
1365 r[8] = 0;
1366 r[9] = 0;
1367 r[10] = 1;
1368 r[11] = 0;
1369 r[12] = x;
1370 r[13] = y;
1371 r[14] = z;
1372 r[15] = 1;
1374 return r;
1375 };
1377 /*
1378 * Function: M4x4.makeTranslate1
1379 */
1380 M4x4.makeTranslate1 = function M4x4_makeTranslate1 (k, r) {
1381 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1383 return M4x4.makeTranslate3(k, k, k, r);
1384 };
1386 /*
1387 * Function: M4x4.makeTranslate
1388 */
1389 M4x4.makeTranslate = function M4x4_makeTranslate (v, r) {
1390 //MathUtils_assert(v.length == 3, "v.length == 3");
1391 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1393 return M4x4.makeTranslate3(v[0], v[1], v[2], r);
1394 };
1396 /*
1397 * Function: M4x4.translate3Self
1398 */
1399 M4x4.translate3Self = function M4x4_translate3Self (x, y, z, m) {
1400 //MathUtils_assert(m.length == 16, "m.length == 16");
1401 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1402 m[12] += m[0] * x + m[4] * y + m[8] * z;
1403 m[13] += m[1] * x + m[5] * y + m[9] * z;
1404 m[14] += m[2] * x + m[6] * y + m[10] * z;
1405 m[15] += m[3] * x + m[7] * y + m[11] * z;
1406 return m;
1407 };
1409 /*
1410 * Function: M4x4.translate3
1411 */
1412 M4x4.translate3 = function M4x4_translate3 (x, y, z, m, r) {
1413 //MathUtils_assert(m.length == 16, "m.length == 16");
1414 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1416 if (r == m) {
1417 m[12] += m[0] * x + m[4] * y + m[8] * z;
1418 m[13] += m[1] * x + m[5] * y + m[9] * z;
1419 m[14] += m[2] * x + m[6] * y + m[10] * z;
1420 m[15] += m[3] * x + m[7] * y + m[11] * z;
1421 return m;
1424 if (r == undefined)
1425 r = new MJS_FLOAT_ARRAY_TYPE(16);
1427 var m11 = m[0];
1428 var m21 = m[1];
1429 var m31 = m[2];
1430 var m41 = m[3];
1431 var m12 = m[4];
1432 var m22 = m[5];
1433 var m32 = m[6];
1434 var m42 = m[7];
1435 var m13 = m[8];
1436 var m23 = m[9];
1437 var m33 = m[10];
1438 var m43 = m[11];
1441 r[0] = m11;
1442 r[1] = m21;
1443 r[2] = m31;
1444 r[3] = m41;
1445 r[4] = m12;
1446 r[5] = m22;
1447 r[6] = m32;
1448 r[7] = m42;
1449 r[8] = m13;
1450 r[9] = m23;
1451 r[10] = m33;
1452 r[11] = m43;
1453 r[12] = m11 * x + m12 * y + m13 * z + m[12];
1454 r[13] = m21 * x + m22 * y + m23 * z + m[13];
1455 r[14] = m31 * x + m32 * y + m33 * z + m[14];
1456 r[15] = m41 * x + m42 * y + m43 * z + m[15];
1458 return r;
1459 };
1461 /*
1462 * Function: M4x4.translate1
1463 */
1464 M4x4.translate1 = function M4x4_translate1 (k, m, r) {
1465 //MathUtils_assert(m.length == 16, "m.length == 16");
1466 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1468 return M4x4.translate3(k, k, k, m, r);
1469 };
1470 /*
1471 * Function: M4x4.translateSelf
1472 */
1473 M4x4.translateSelf = function M4x4_translateSelf (v, m) {
1474 //MathUtils_assert(v.length == 3, "v.length == 3");
1475 //MathUtils_assert(m.length == 16, "m.length == 16");
1476 var x=v[0], y=v[1], z=v[2];
1477 m[12] += m[0] * x + m[4] * y + m[8] * z;
1478 m[13] += m[1] * x + m[5] * y + m[9] * z;
1479 m[14] += m[2] * x + m[6] * y + m[10] * z;
1480 m[15] += m[3] * x + m[7] * y + m[11] * z;
1481 return m;
1482 };
1483 /*
1484 * Function: M4x4.translate
1485 */
1486 M4x4.translate = function M4x4_translate (v, m, r) {
1487 //MathUtils_assert(v.length == 3, "v.length == 3");
1488 //MathUtils_assert(m.length == 16, "m.length == 16");
1489 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1490 var x=v[0], y=v[1], z=v[2];
1491 if (r == m) {
1492 m[12] += m[0] * x + m[4] * y + m[8] * z;
1493 m[13] += m[1] * x + m[5] * y + m[9] * z;
1494 m[14] += m[2] * x + m[6] * y + m[10] * z;
1495 m[15] += m[3] * x + m[7] * y + m[11] * z;
1496 return m;
1499 if (r == undefined)
1500 r = new MJS_FLOAT_ARRAY_TYPE(16);
1502 var m11 = m[0];
1503 var m21 = m[1];
1504 var m31 = m[2];
1505 var m41 = m[3];
1506 var m12 = m[4];
1507 var m22 = m[5];
1508 var m32 = m[6];
1509 var m42 = m[7];
1510 var m13 = m[8];
1511 var m23 = m[9];
1512 var m33 = m[10];
1513 var m43 = m[11];
1515 r[0] = m11;
1516 r[1] = m21;
1517 r[2] = m31;
1518 r[3] = m41;
1519 r[4] = m12;
1520 r[5] = m22;
1521 r[6] = m32;
1522 r[7] = m42;
1523 r[8] = m13;
1524 r[9] = m23;
1525 r[10] = m33;
1526 r[11] = m43;
1527 r[12] = m11 * x + m12 * y + m13 * z + m[12];
1528 r[13] = m21 * x + m22 * y + m23 * z + m[13];
1529 r[14] = m31 * x + m32 * y + m33 * z + m[14];
1530 r[15] = m41 * x + m42 * y + m43 * z + m[15];
1532 return r;
1533 };
1535 /*
1536 * Function: M4x4.makeLookAt
1537 */
1538 M4x4.makeLookAt = function M4x4_makeLookAt (eye, center, up, r) {
1539 //MathUtils_assert(eye.length == 3, "eye.length == 3");
1540 //MathUtils_assert(center.length == 3, "center.length == 3");
1541 //MathUtils_assert(up.length == 3, "up.length == 3");
1542 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1544 var z = V3.direction(eye, center, V3._temp1);
1545 var x = V3.normalize(V3.cross(up, z, V3._temp2), V3._temp2);
1546 var y = V3.normalize(V3.cross(z, x, V3._temp3), V3._temp3);
1548 var tm1 = M4x4._temp1;
1549 var tm2 = M4x4._temp2;
1551 tm1[0] = x[0];
1552 tm1[1] = y[0];
1553 tm1[2] = z[0];
1554 tm1[3] = 0;
1555 tm1[4] = x[1];
1556 tm1[5] = y[1];
1557 tm1[6] = z[1];
1558 tm1[7] = 0;
1559 tm1[8] = x[2];
1560 tm1[9] = y[2];
1561 tm1[10] = z[2];
1562 tm1[11] = 0;
1563 tm1[12] = 0;
1564 tm1[13] = 0;
1565 tm1[14] = 0;
1566 tm1[15] = 1;
1568 tm2[0] = 1; tm2[1] = 0; tm2[2] = 0; tm2[3] = 0;
1569 tm2[4] = 0; tm2[5] = 1; tm2[6] = 0; tm2[7] = 0;
1570 tm2[8] = 0; tm2[9] = 0; tm2[10] = 1; tm2[11] = 0;
1571 tm2[12] = -eye[0]; tm2[13] = -eye[1]; tm2[14] = -eye[2]; tm2[15] = 1;
1573 if (r == undefined)
1574 r = new MJS_FLOAT_ARRAY_TYPE(16);
1575 return M4x4.mul(tm1, tm2, r);
1576 };
1578 /*
1579 * Function: M4x4.transposeSelf
1580 */
1581 M4x4.transposeSelf = function M4x4_transposeSelf (m) {
1582 //MathUtils_assert(m.length == 16, "m.length == 16");
1583 var tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1584 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1585 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1586 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1587 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1588 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1589 return m;
1590 };
1591 /*
1592 * Function: M4x4.transpose
1593 */
1594 M4x4.transpose = function M4x4_transpose (m, r) {
1595 //MathUtils_assert(m.length == 16, "m.length == 16");
1596 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1598 if (m == r) {
1599 var tmp = 0.0;
1600 tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1601 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1602 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1603 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1604 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1605 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1606 return m;
1609 if (r == undefined)
1610 r = new MJS_FLOAT_ARRAY_TYPE(16);
1612 r[0] = m[0]; r[1] = m[4]; r[2] = m[8]; r[3] = m[12];
1613 r[4] = m[1]; r[5] = m[5]; r[6] = m[9]; r[7] = m[13];
1614 r[8] = m[2]; r[9] = m[6]; r[10] = m[10]; r[11] = m[14];
1615 r[12] = m[3]; r[13] = m[7]; r[14] = m[11]; r[15] = m[15];
1617 return r;
1618 };
1621 /*
1622 * Function: M4x4.transformPoint
1623 */
1624 M4x4.transformPoint = function M4x4_transformPoint (m, v, r) {
1625 //MathUtils_assert(m.length == 16, "m.length == 16");
1626 //MathUtils_assert(v.length == 3, "v.length == 3");
1627 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1628 if (r == undefined)
1629 r = new MJS_FLOAT_ARRAY_TYPE(3);
1631 var v0 = v[0], v1 = v[1], v2 = v[2];
1633 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1634 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1635 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1636 var w = m[3] * v0 + m[7] * v1 + m[11] * v2 + m[15];
1638 if (w != 1.0) {
1639 r[0] /= w;
1640 r[1] /= w;
1641 r[2] /= w;
1644 return r;
1645 };
1647 /*
1648 * Function: M4x4.transformLine
1649 */
1650 M4x4.transformLine = function M4x4_transformLine(m, v, r) {
1651 //MathUtils_assert(m.length == 16, "m.length == 16");
1652 //MathUtils_assert(v.length == 3, "v.length == 3");
1653 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1654 if (r == undefined)
1655 r = new MJS_FLOAT_ARRAY_TYPE(3);
1657 var v0 = v[0], v1 = v[1], v2 = v[2];
1658 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1659 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1660 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1661 var w = m[3] * v0 + m[7] * v1 + m[11] * v2;
1663 if (w != 1.0) {
1664 r[0] /= w;
1665 r[1] /= w;
1666 r[2] /= w;
1669 return r;
1670 };
1673 /*
1674 * Function: M4x4.transformPointAffine
1675 */
1676 M4x4.transformPointAffine = function M4x4_transformPointAffine (m, v, r) {
1677 //MathUtils_assert(m.length == 16, "m.length == 16");
1678 //MathUtils_assert(v.length == 3, "v.length == 3");
1679 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1680 if (r == undefined)
1681 r = new MJS_FLOAT_ARRAY_TYPE(3);
1683 var v0 = v[0], v1 = v[1], v2 = v[2];
1685 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1686 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1687 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1689 return r;
1690 };
1692 /*
1693 * Function: M4x4.transformLineAffine
1694 */
1695 M4x4.transformLineAffine = function M4x4_transformLineAffine(m, v, r) {
1696 //MathUtils_assert(m.length == 16, "m.length == 16");
1697 //MathUtils_assert(v.length == 3, "v.length == 3");
1698 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1699 if (r == undefined)
1700 r = new MJS_FLOAT_ARRAY_TYPE(3);
1702 var v0 = v[0], v1 = v[1], v2 = v[2];
1703 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1704 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1705 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1707 return r;
1708 };
1710 M4x4.makeBasis = function M4x4_makeBasis(vx,vy,vz) {
1712 var r = new MJS_FLOAT_ARRAY_TYPE(16);
1714 r[0] = vx[0];
1715 r[1] = vx[1];
1716 r[2] = vx[2];
1717 r[3] = 0;
1718 r[4] = vy[0];
1719 r[5] = vy[1];
1720 r[6] = vy[2];
1721 r[7] = 0;
1722 r[8] = vz[0];
1723 r[9] = vz[1];
1724 r[10] = vz[2];
1725 r[11] = 0;
1726 r[12] = 0;
1727 r[13] = 0;
1728 r[14] = 0;
1729 r[15] = 1;
1731 return r;
1733 };
1735 return {
1736 V3: V3,
1737 v3: F3(V3.$),
1738 v3getX: V3.getX,
1739 v3getY: V3.getY,
1740 v3getZ: V3.getZ,
1741 v3setX: F2(V3.setX),
1742 v3setY: F2(V3.setY),
1743 v3setZ: F2(V3.setZ),
1744 toTuple3: V3.toTuple3,
1745 toRecord3: V3.toRecord3,
1746 fromTuple3: V3.fromTuple3,
1747 fromRecord3: V3.fromRecord3,
1748 v3add: F2(V3.add),
1749 v3sub: F2(V3.sub),
1750 v3neg: V3.neg,
1751 v3direction: F2(V3.direction),
1752 v3length: V3.length,
1753 v3lengthSquared: V3.lengthSquared,
1754 v3distance: F2(V3.distance),
1755 v3distanceSquared: F2(V3.distanceSquared),
1756 v3normalize: V3.normalize,
1757 v3scale: F2(V3.scale),
1758 v3dot: F2(V3.dot),
1759 v3cross: F2(V3.cross),
1760 v3mul4x4: F2(V3.mul4x4),
1761 M4x4:M4x4,
1762 m4x4identity: M4x4.identity,
1763 m4x4topLeft3x3: M4x4.topLeft3x3,
1764 m4x4inverseOrthonormal: M4x4.inverseOrthonormal,
1765 m4x4inverseTo3x3: M4x4.inverseTo3x3,
1766 m4x4makeFrustum: F6(M4x4.makeFrustum),
1767 m4x4makePerspective: F4(M4x4.makePerspective),
1768 m4x4makeOrtho: F6(M4x4.makeOrtho),
1769 m4x4makeOrtho2D: F4(M4x4.makeOrtho2D),
1770 m4x4mul: F2(M4x4.mul),
1771 m4x4Affine: F2(M4x4.mulAffine),
1772 m4x4makeRotate: F2(M4x4.makeRotate),
1773 m4x4rotate: F3(M4x4.rotate),
1774 m4x4makeScale3: F3(M4x4.makeScale3),
1775 m4x4makeScale1: M4x4.makeScale1,
1776 m4x4makeScale: M4x4.makeScale,
1777 m4x4scale3: F4(M4x4.scale3),
1778 m4x4scale: F2(M4x4.scale),
1779 m4x4makeTranslate3: F3(M4x4.makeTranslate3),
1780 m4x4makeTranslate: M4x4.makeTranslate,
1781 m4x4translate3: F4(M4x4.translate3),
1782 m4x4translate: F2(M4x4.translate),
1783 m4x4makeLookAt: F3(M4x4.makeLookAt),
1784 m4x4transpose: M4x4.transpose,
1785 m4x4transformPoint: F2(M4x4.transformPoint),
1786 m4x4makeBasis: F3(M4x4.makeBasis),
1787 };