on bf13e7d help sign in
1761 lines 52 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 }
145 V3.toTuple3 = function V3_toTuple3(a) {
146 return {
147 ctor:"_Tuple3",
148 _0:a[0],
149 _1:a[1],
150 _2:a[2]
151 };
152 };
153 V3.fromTuple3 = function V3_fromTuple3(t) {
154 return new MJS_FLOAT_ARRAY_TYPE([t._0, t._1, t._2]);
155 };
157 V3.toRecord3 = function V3_toRecord3(a) {
158 return {
159 _:{},
160 x:a[0],
161 y:a[1],
162 z:a[2]
163 };
164 };
165 V3.fromRecord3 = function V3_fromRecord3(r) {
166 return new MJS_FLOAT_ARRAY_TYPE([r.x, r.y, r.z]);
167 };
169 /*
170 * Function: V3.add
171 *
172 * Perform r = a + b.
173 *
174 * Parameters:
175 *
176 * a - the first vector operand
177 * b - the second vector operand
178 * r - optional vector to store the result in
179 *
180 * Returns:
181 *
182 * If r is specified, returns r after performing the operation.
183 * Otherwise, returns a new 3-element vector with the result.
184 */
185 V3.add = function V3_add(a, b, r) {
186 //MathUtils_assert(a.length == 3, "a.length == 3");
187 //MathUtils_assert(b.length == 3, "b.length == 3");
188 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
190 if (r == undefined)
191 r = new MJS_FLOAT_ARRAY_TYPE(3);
192 r[0] = a[0] + b[0];
193 r[1] = a[1] + b[1];
194 r[2] = a[2] + b[2];
195 return r;
196 };
198 /*
199 * Function: V3.sub
200 *
201 * Perform
202 * r = a - b.
203 *
204 * Parameters:
205 *
206 * a - the first vector operand
207 * b - the second vector operand
208 * r - optional vector to store the result in
209 *
210 * Returns:
211 *
212 * If r is specified, returns r after performing the operation.
213 * Otherwise, returns a new 3-element vector with the result.
214 */
215 V3.sub = function V3_sub(a, b, r) {
216 //MathUtils_assert(a.length == 3, "a.length == 3");
217 //MathUtils_assert(b.length == 3, "b.length == 3");
218 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
220 if (r == undefined)
221 r = new MJS_FLOAT_ARRAY_TYPE(3);
222 r[0] = a[0] - b[0];
223 r[1] = a[1] - b[1];
224 r[2] = a[2] - b[2];
225 return r;
226 };
228 /*
229 * Function: V3.neg
230 *
231 * Perform
232 * r = - a.
233 *
234 * Parameters:
235 *
236 * a - the vector operand
237 * r - optional vector to store the result in
238 *
239 * Returns:
240 *
241 * If r is specified, returns r after performing the operation.
242 * Otherwise, returns a new 3-element vector with the result.
243 */
244 V3.neg = function V3_neg(a, r) {
245 //MathUtils_assert(a.length == 3, "a.length == 3");
246 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
248 if (r == undefined)
249 r = new MJS_FLOAT_ARRAY_TYPE(3);
250 r[0] = - a[0];
251 r[1] = - a[1];
252 r[2] = - a[2];
253 return r;
254 };
256 /*
257 * Function: V3.direction
258 *
259 * Perform
260 * r = (a - b) / |a - b|. The result is the normalized
261 * direction from a to b.
262 *
263 * Parameters:
264 *
265 * a - the first vector operand
266 * b - the second vector operand
267 * r - optional vector to store the result in
268 *
269 * Returns:
270 *
271 * If r is specified, returns r after performing the operation.
272 * Otherwise, returns a new 3-element vector with the result.
273 */
274 V3.direction = function V3_direction(a, b, r) {
275 //MathUtils_assert(a.length == 3, "a.length == 3");
276 //MathUtils_assert(b.length == 3, "b.length == 3");
277 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
279 if (r == undefined)
280 r = new MJS_FLOAT_ARRAY_TYPE(3);
281 return V3.normalize(V3.sub(a, b, r), r);
282 };
284 /*
285 * Function: V3.length
286 *
287 * Perform r = |a|.
288 *
289 * Parameters:
290 *
291 * a - the vector operand
292 *
293 * Returns:
294 *
295 * The length of the given vector.
296 */
297 V3.length = function V3_length(a) {
298 //MathUtils_assert(a.length == 3, "a.length == 3");
300 return Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
301 };
303 /*
304 * Function: V3.lengthSquard
305 *
306 * Perform r = |a|*|a|.
307 *
308 * Parameters:
309 *
310 * a - the vector operand
311 *
312 * Returns:
313 *
314 * The square of the length of the given vector.
315 */
316 V3.lengthSquared = function V3_lengthSquared(a) {
317 //MathUtils_assert(a.length == 3, "a.length == 3");
319 return a[0]*a[0] + a[1]*a[1] + a[2]*a[2];
320 };
322 /*
323 * Function: V3.normalize
324 *
325 * Perform r = a / |a|.
326 *
327 * Parameters:
328 *
329 * a - the vector operand
330 * r - optional vector to store the result in
331 *
332 * Returns:
333 *
334 * If r is specified, returns r after performing the operation.
335 * Otherwise, returns a new 3-element vector with the result.
336 */
337 V3.normalize = function V3_normalize(a, r) {
338 //MathUtils_assert(a.length == 3, "a.length == 3");
339 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
341 if (r == undefined)
342 r = new MJS_FLOAT_ARRAY_TYPE(3);
343 var im = 1.0 / V3.length(a);
344 r[0] = a[0] * im;
345 r[1] = a[1] * im;
346 r[2] = a[2] * im;
347 return r;
348 };
350 /*
351 * Function: V3.scale
352 *
353 * Perform r = a * k.
354 *
355 * Parameters:
356 *
357 * a - the vector operand
358 * k - a scalar value
359 * r - optional vector to store the result in
360 *
361 * Returns:
362 *
363 * If r is specified, returns r after performing the operation.
364 * Otherwise, returns a new 3-element vector with the result.
365 */
366 V3.scale = function V3_scale(a, k, r) {
367 //MathUtils_assert(a.length == 3, "a.length == 3");
368 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
370 if (r == undefined)
371 r = new MJS_FLOAT_ARRAY_TYPE(3);
372 r[0] = a[0] * k;
373 r[1] = a[1] * k;
374 r[2] = a[2] * k;
375 return r;
376 };
378 /*
379 * Function: V3.dot
380 *
381 * Perform
382 * r = dot(a, b).
383 *
384 * Parameters:
385 *
386 * a - the first vector operand
387 * b - the second vector operand
388 *
389 * Returns:
390 *
391 * The dot product of a and b.
392 */
393 V3.dot = function V3_dot(a, b) {
394 //MathUtils_assert(a.length == 3, "a.length == 3");
395 //MathUtils_assert(b.length == 3, "b.length == 3");
397 return a[0] * b[0] +
398 a[1] * b[1] +
399 a[2] * b[2];
400 };
402 /*
403 * Function: V3.cross
404 *
405 * Perform r = a x b.
406 *
407 * Parameters:
408 *
409 * a - the first vector operand
410 * b - the second vector operand
411 * r - optional vector to store the result in
412 *
413 * Returns:
414 *
415 * If r is specified, returns r after performing the operation.
416 * Otherwise, returns a new 3-element vector with the result.
417 */
418 V3.cross = function V3_cross(a, b, r) {
419 //MathUtils_assert(a.length == 3, "a.length == 3");
420 //MathUtils_assert(b.length == 3, "b.length == 3");
421 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
423 if (r == undefined)
424 r = new MJS_FLOAT_ARRAY_TYPE(3);
425 r[0] = a[1]*b[2] - a[2]*b[1];
426 r[1] = a[2]*b[0] - a[0]*b[2];
427 r[2] = a[0]*b[1] - a[1]*b[0];
428 return r;
429 };
431 /*
432 * Function: V3.mul4x4
433 *
434 * Perform
435 * r = m * v.
436 *
437 * Parameters:
438 *
439 * m - the 4x4 matrix operand
440 * v - the 3-element vector operand
441 * r - optional vector to store the result in
442 *
443 * Returns:
444 *
445 * If r is specified, returns r after performing the operation.
446 * Otherwise, returns a new 3-element vector with the result.
447 * The 4-element result vector is divided by the w component
448 * and returned as a 3-element vector.
449 */
450 V3.mul4x4 = function V3_mul4x4(m, v, r) {
451 //MathUtils_assert(m.length == 16, "m.length == 16");
452 //MathUtils_assert(v.length == 3, "v.length == 3");
453 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
455 var w;
456 var tmp = V3._temp1;
457 if (r == undefined)
458 r = new MJS_FLOAT_ARRAY_TYPE(3);
459 tmp[0] = m[ 3];
460 tmp[1] = m[ 7];
461 tmp[2] = m[11];
462 w = V3.dot(v, tmp) + m[15];
463 tmp[0] = m[ 0];
464 tmp[1] = m[ 4];
465 tmp[2] = m[ 8];
466 r[0] = (V3.dot(v, tmp) + m[12])/w;
467 tmp[0] = m[ 1];
468 tmp[1] = m[ 5];
469 tmp[2] = m[ 9];
470 r[1] = (V3.dot(v, tmp) + m[13])/w;
471 tmp[0] = m[ 2];
472 tmp[1] = m[ 6];
473 tmp[2] = m[10];
474 r[2] = (V3.dot(v, tmp) + m[14])/w;
475 return r;
476 };
478 /*
479 * Class: M4x4
480 *
481 * Methods for working with 4x4 matrices. A matrix is represented by a 16-element array
482 * in column-major order. Any valid JavaScript array type may be used, but if new
483 * matrices are created they are created using the configured MJS_FLOAT_ARRAY_TYPE.
484 */
486 var M4x4 = { };
488 M4x4._temp1 = new MJS_FLOAT_ARRAY_TYPE(16);
489 M4x4._temp2 = new MJS_FLOAT_ARRAY_TYPE(16);
491 if (MJS_FLOAT_ARRAY_TYPE == Array) {
492 M4x4.I = [1.0, 0.0, 0.0, 0.0,
493 0.0, 1.0, 0.0, 0.0,
494 0.0, 0.0, 1.0, 0.0,
495 0.0, 0.0, 0.0, 1.0];
497 M4x4.$ = function M4x4_$(m00, m01, m02, m03,
498 m04, m05, m06, m07,
499 m08, m09, m10, m11,
500 m12, m13, m14, m15)
501 {
502 return [m00, m01, m02, m03,
503 m04, m05, m06, m07,
504 m08, m09, m10, m11,
505 m12, m13, m14, m15];
506 };
507 } else {
508 M4x4.I = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0, 0.0,
509 0.0, 1.0, 0.0, 0.0,
510 0.0, 0.0, 1.0, 0.0,
511 0.0, 0.0, 0.0, 1.0]);
513 /*
514 * Function: M4x4.$
515 *
516 * Creates a new 4x4 matrix with the given values.
517 *
518 * Parameters:
519 *
520 * m00..m15 - the 16 elements of the new matrix.
521 *
522 * Returns:
523 *
524 * A new matrix filled with the given argument values.
525 */
526 M4x4.$ = function M4x4_$(m00, m01, m02, m03,
527 m04, m05, m06, m07,
528 m08, m09, m10, m11,
529 m12, m13, m14, m15)
530 {
531 return new MJS_FLOAT_ARRAY_TYPE([m00, m01, m02, m03,
532 m04, m05, m06, m07,
533 m08, m09, m10, m11,
534 m12, m13, m14, m15]);
535 };
536 }
538 M4x4.identity = M4x4.I;
540 /*
541 * Function: M4x4.topLeft3x3
542 *
543 * Return the top left 3x3 matrix from the given 4x4 matrix m.
544 *
545 * Parameters:
546 *
547 * m - the matrix
548 * r - optional 3x3 matrix to store the result in
549 *
550 * Returns:
551 *
552 * If r is specified, returns r after performing the operation.
553 * Otherwise, returns a new 3x3 matrix with the result.
554 */
555 M4x4.topLeft3x3 = function M4x4_topLeft3x3(m, r) {
556 //MathUtils_assert(m.length == 16, "m.length == 16");
557 //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
559 if (r == undefined)
560 r = new MJS_FLOAT_ARRAY_TYPE(9);
561 r[0] = m[0]; r[1] = m[1]; r[2] = m[2];
562 r[3] = m[4]; r[4] = m[5]; r[5] = m[6];
563 r[6] = m[8]; r[7] = m[9]; r[8] = m[10];
564 return r;
565 };
567 /*
568 * Function: M4x4.inverseOrthonormal
569 *
570 * Computes the inverse of the given matrix m, assuming that
571 * the matrix is orthonormal.
572 *
573 * Parameters:
574 *
575 * m - the matrix
576 * r - optional 4x4 matrix to store the result in
577 *
578 * Returns:
579 *
580 * If r is specified, returns r after performing the operation.
581 * Otherwise, returns a new 4x4 matrix with the result.
582 */
583 M4x4.inverseOrthonormal = function M4x4_inverseOrthonormal(m, r) {
584 //MathUtils_assert(m.length == 16, "m.length == 16");
585 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
586 //MathUtils_assert(m != r, "m != r");
588 if (r == undefined)
589 r = new MJS_FLOAT_ARRAY_TYPE(16);
590 M4x4.transpose(m, r);
591 var t = [m[12], m[13], m[14]];
592 r[3] = r[7] = r[11] = 0;
593 r[12] = -V3.dot([r[0], r[4], r[8]], t);
594 r[13] = -V3.dot([r[1], r[5], r[9]], t);
595 r[14] = -V3.dot([r[2], r[6], r[10]], t);
596 return r;
597 };
599 /*
600 * Function: M4x4.inverseTo3x3
601 *
602 * Computes the inverse of the given matrix m, but calculates
603 * only the top left 3x3 values of the result.
604 *
605 * Parameters:
606 *
607 * m - the matrix
608 * r - optional 3x3 matrix to store the result in
609 *
610 * Returns:
611 *
612 * If r is specified, returns r after performing the operation.
613 * Otherwise, returns a new 3x3 matrix with the result.
614 */
615 M4x4.inverseTo3x3 = function M4x4_inverseTo3x3(m, r) {
616 //MathUtils_assert(m.length == 16, "m.length == 16");
617 //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
619 if (r == undefined)
620 r = new MJS_FLOAT_ARRAY_TYPE(9);
622 var a11 = m[10]*m[5]-m[6]*m[9],
623 a21 = -m[10]*m[1]+m[2]*m[9],
624 a31 = m[6]*m[1]-m[2]*m[5],
625 a12 = -m[10]*m[4]+m[6]*m[8],
626 a22 = m[10]*m[0]-m[2]*m[8],
627 a32 = -m[6]*m[0]+m[2]*m[4],
628 a13 = m[9]*m[4]-m[5]*m[8],
629 a23 = -m[9]*m[0]+m[1]*m[8],
630 a33 = m[5]*m[0]-m[1]*m[4];
631 var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13);
632 if (det == 0) // no inverse
633 throw "matrix not invertible";
634 var idet = 1.0 / det;
636 r[0] = idet*a11;
637 r[1] = idet*a21;
638 r[2] = idet*a31;
639 r[3] = idet*a12;
640 r[4] = idet*a22;
641 r[5] = idet*a32;
642 r[6] = idet*a13;
643 r[7] = idet*a23;
644 r[8] = idet*a33;
646 return r;
647 };
649 /*
650 * Function: M4x4.makeFrustum
651 *
652 * Creates a matrix for a projection frustum with the given parameters.
653 *
654 * Parameters:
655 *
656 * left - the left coordinate of the frustum
657 * right- the right coordinate of the frustum
658 * bottom - the bottom coordinate of the frustum
659 * top - the top coordinate of the frustum
660 * znear - the near z distance of the frustum
661 * zfar - the far z distance of the frustum
662 * r - optional 4x4 matrix to store the result in
663 *
664 * Returns:
665 *
666 * If r is specified, returns r after creating the projection matrix.
667 * Otherwise, returns a new 4x4 matrix.
668 */
669 M4x4.makeFrustum = function M4x4_makeFrustum(left, right, bottom, top, znear, zfar, r) {
670 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
672 if (r == undefined)
673 r = new MJS_FLOAT_ARRAY_TYPE(16);
675 var X = 2*znear/(right-left);
676 var Y = 2*znear/(top-bottom);
677 var A = (right+left)/(right-left);
678 var B = (top+bottom)/(top-bottom);
679 var C = -(zfar+znear)/(zfar-znear);
680 var D = -2*zfar*znear/(zfar-znear);
682 r[0] = 2*znear/(right-left);
683 r[1] = 0;
684 r[2] = 0;
685 r[3] = 0;
686 r[4] = 0;
687 r[5] = 2*znear/(top-bottom);
688 r[6] = 0;
689 r[7] = 0;
690 r[8] = (right+left)/(right-left);
691 r[9] = (top+bottom)/(top-bottom);
692 r[10] = -(zfar+znear)/(zfar-znear);
693 r[11] = -1;
694 r[12] = 0;
695 r[13] = 0;
696 r[14] = -2*zfar*znear/(zfar-znear);
697 r[15] = 0;
699 return r;
700 };
702 /*
703 * Function: M4x4.makePerspective
704 *
705 * Creates a matrix for a perspective projection with the given parameters.
706 *
707 * Parameters:
708 *
709 * fovy - field of view in the y axis, in degrees
710 * aspect - aspect ratio
711 * znear - the near z distance of the projection
712 * zfar - the far z distance of the projection
713 * r - optional 4x4 matrix to store the result in
714 *
715 * Returns:
716 *
717 * If r is specified, returns r after creating the projection matrix.
718 * Otherwise, returns a new 4x4 matrix.
719 */
720 M4x4.makePerspective = function M4x4_makePerspective (fovy, aspect, znear, zfar, r) {
721 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
723 var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
724 var ymin = -ymax;
725 var xmin = ymin * aspect;
726 var xmax = ymax * aspect;
728 return M4x4.makeFrustum(xmin, xmax, ymin, ymax, znear, zfar, r);
729 };
731 /*
732 * Function: M4x4.makeOrtho
733 *
734 * Creates a matrix for an orthogonal frustum projection with the given parameters.
735 *
736 * Parameters:
737 *
738 * left - the left coordinate of the frustum
739 * right- the right coordinate of the frustum
740 * bottom - the bottom coordinate of the frustum
741 * top - the top coordinate of the frustum
742 * znear - the near z distance of the frustum
743 * zfar - the far z distance of the frustum
744 * r - optional 4x4 matrix to store the result in
745 *
746 * Returns:
747 *
748 * If r is specified, returns r after creating the projection matrix.
749 * Otherwise, returns a new 4x4 matrix.
750 */
751 M4x4.makeOrtho = function M4x4_makeOrtho (left, right, bottom, top, znear, zfar, r) {
752 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
754 if (r == undefined)
755 r = new MJS_FLOAT_ARRAY_TYPE(16);
757 var tX = -(right+left)/(right-left);
758 var tY = -(top+bottom)/(top-bottom);
759 var tZ = -(zfar+znear)/(zfar-znear);
760 var X = 2 / (right-left);
761 var Y = 2 / (top-bottom);
762 var Z = -2 / (zfar-znear);
764 r[0] = 2 / (right-left);
765 r[1] = 0;
766 r[2] = 0;
767 r[3] = 0;
768 r[4] = 0;
769 r[5] = 2 / (top-bottom);
770 r[6] = 0;
771 r[7] = 0;
772 r[8] = 0;
773 r[9] = 0;
774 r[10] = -2 / (zfar-znear);
775 r[11] = 0;
776 r[12] = -(right+left)/(right-left);
777 r[13] = -(top+bottom)/(top-bottom);
778 r[14] = -(zfar+znear)/(zfar-znear);
779 r[15] = 1;
781 return r;
782 };
784 /*
785 * Function: M4x4.makeOrtho2D
786 *
787 * Creates a matrix for a 2D orthogonal frustum projection with the given parameters.
788 * znear and zfar are assumed to be -1 and 1, respectively.
789 *
790 * Parameters:
791 *
792 * left - the left coordinate of the frustum
793 * right- the right coordinate of the frustum
794 * bottom - the bottom coordinate of the frustum
795 * top - the top coordinate of the frustum
796 * r - optional 4x4 matrix to store the result in
797 *
798 * Returns:
799 *
800 * If r is specified, returns r after creating the projection matrix.
801 * Otherwise, returns a new 4x4 matrix.
802 */
803 M4x4.makeOrtho2D = function M4x4_makeOrtho2D (left, right, bottom, top, r) {
804 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
806 return M4x4.makeOrtho(left, right, bottom, top, -1, 1, r);
807 };
809 /*
810 * Function: M4x4.mul
811 *
812 * Performs r = a * b.
813 *
814 * Parameters:
815 *
816 * a - the first matrix operand
817 * b - the second matrix operand
818 * r - optional 4x4 matrix to store the result in
819 *
820 * Returns:
821 *
822 * If r is specified, returns r after performing the operation.
823 * Otherwise, returns a new 4x4 matrix with the result.
824 */
825 M4x4.mul = function M4x4_mul(a, b, r) {
826 //MathUtils_assert(a.length == 16, "a.length == 16");
827 //MathUtils_assert(b.length == 16, "b.length == 16");
828 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
829 //MathUtils_assert(a != r && b != r, "a != r && b != r");
831 if (r == undefined)
832 r = new MJS_FLOAT_ARRAY_TYPE(16);
834 var a11 = a[0];
835 var a21 = a[1];
836 var a31 = a[2];
837 var a41 = a[3];
838 var a12 = a[4];
839 var a22 = a[5];
840 var a32 = a[6];
841 var a42 = a[7];
842 var a13 = a[8];
843 var a23 = a[9];
844 var a33 = a[10];
845 var a43 = a[11];
846 var a14 = a[12];
847 var a24 = a[13];
848 var a34 = a[14];
849 var a44 = a[15];
851 var b11 = b[0];
852 var b21 = b[1];
853 var b31 = b[2];
854 var b41 = b[3];
855 var b12 = b[4];
856 var b22 = b[5];
857 var b32 = b[6];
858 var b42 = b[7];
859 var b13 = b[8];
860 var b23 = b[9];
861 var b33 = b[10];
862 var b43 = b[11];
863 var b14 = b[12];
864 var b24 = b[13];
865 var b34 = b[14];
866 var b44 = b[15];
868 r[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
869 r[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
870 r[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
871 r[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
872 r[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
873 r[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
874 r[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
875 r[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
876 r[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
877 r[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
878 r[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
879 r[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
880 r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
881 r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
882 r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
883 r[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
885 return r;
886 };
888 /*
889 * Function: M4x4.mulAffine
890 *
891 * Performs r = a * b, assuming a and b are affine (elements 3,7,11,15 = 0,0,0,1)
892 *
893 * Parameters:
894 *
895 * a - the first matrix operand
896 * b - the second matrix operand
897 * r - optional 4x4 matrix to store the result in
898 *
899 * Returns:
900 *
901 * If r is specified, returns r after performing the operation.
902 * Otherwise, returns a new 4x4 matrix with the result.
903 */
904 M4x4.mulAffine = function M4x4_mulAffine(a, b, r) {
905 //MathUtils_assert(a.length == 16, "a.length == 16");
906 //MathUtils_assert(b.length == 16, "b.length == 16");
907 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
908 //MathUtils_assert(a != r && b != r, "a != r && b != r");
910 if (r == undefined)
911 r = new MJS_FLOAT_ARRAY_TYPE(16);
912 var a11 = a[0];
913 var a21 = a[1];
914 var a31 = a[2];
915 var a12 = a[4];
916 var a22 = a[5];
917 var a32 = a[6];
918 var a13 = a[8];
919 var a23 = a[9];
920 var a33 = a[10];
921 var a14 = a[12];
922 var a24 = a[13];
923 var a34 = a[14];
925 var b11 = b[0];
926 var b21 = b[1];
927 var b31 = b[2];
928 var b12 = b[4];
929 var b22 = b[5];
930 var b32 = b[6];
931 var b13 = b[8];
932 var b23 = b[9];
933 var b33 = b[10];
934 var b14 = b[12];
935 var b24 = b[13];
936 var b34 = b[14];
938 r[0] = a11 * b11 + a12 * b21 + a13 * b31;
939 r[1] = a21 * b11 + a22 * b21 + a23 * b31;
940 r[2] = a31 * b11 + a32 * b21 + a33 * b31;
941 r[3] = 0;
942 r[4] = a11 * b12 + a12 * b22 + a13 * b32;
943 r[5] = a21 * b12 + a22 * b22 + a23 * b32;
944 r[6] = a31 * b12 + a32 * b22 + a33 * b32;
945 r[7] = 0;
946 r[8] = a11 * b13 + a12 * b23 + a13 * b33;
947 r[9] = a21 * b13 + a22 * b23 + a23 * b33;
948 r[10] = a31 * b13 + a32 * b23 + a33 * b33;
949 r[11] = 0;
950 r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14;
951 r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24;
952 r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34;
953 r[15] = 1;
955 return r;
956 };
958 /*
959 * Function: M4x4.makeRotate
960 *
961 * Creates a transformation matrix for rotation by angle radians about the 3-element vector axis.
962 *
963 * Parameters:
964 *
965 * angle - the angle of rotation, in radians
966 * axis - the axis around which the rotation is performed, a 3-element vector
967 * r - optional 4x4 matrix to store the result in
968 *
969 * Returns:
970 *
971 * If r is specified, returns r after creating the matrix.
972 * Otherwise, returns a new 4x4 matrix with the result.
973 */
974 M4x4.makeRotate = function M4x4_makeRotate(angle, axis, r) {
975 //MathUtils_assert(angle.length == 3, "angle.length == 3");
976 //MathUtils_assert(axis.length == 3, "axis.length == 3");
977 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
979 if (r == undefined)
980 r = new MJS_FLOAT_ARRAY_TYPE(16);
982 axis = V3.normalize(axis, V3._temp1);
983 var x = axis[0], y = axis[1], z = axis[2];
984 var c = Math.cos(angle);
985 var c1 = 1-c;
986 var s = Math.sin(angle);
988 r[0] = x*x*c1+c;
989 r[1] = y*x*c1+z*s;
990 r[2] = z*x*c1-y*s;
991 r[3] = 0;
992 r[4] = x*y*c1-z*s;
993 r[5] = y*y*c1+c;
994 r[6] = y*z*c1+x*s;
995 r[7] = 0;
996 r[8] = x*z*c1+y*s;
997 r[9] = y*z*c1-x*s;
998 r[10] = z*z*c1+c;
999 r[11] = 0;
1000 r[12] = 0;
1001 r[13] = 0;
1002 r[14] = 0;
1003 r[15] = 1;
1005 return r;
1006 };
1008 /*
1009 * Function: M4x4.rotate
1011 * Concatenates a rotation of angle radians about the axis to the give matrix m.
1013 * Parameters:
1015 * angle - the angle of rotation, in radians
1016 * axis - the axis around which the rotation is performed, a 3-element vector
1017 * m - the matrix to concatenate the rotation to
1018 * r - optional 4x4 matrix to store the result in
1020 * Returns:
1022 * If r is specified, returns r after performing the operation.
1023 * Otherwise, returns a new 4x4 matrix with the result.
1024 */
1025 M4x4.rotate = function M4x4_rotate(angle, axis, m, r) {
1026 //MathUtils_assert(angle.length == 3, "angle.length == 3");
1027 //MathUtils_assert(axis.length == 3, "axis.length == 3");
1028 //MathUtils_assert(m.length == 16, "m.length == 16");
1029 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1031 if (r == undefined)
1032 r = new MJS_FLOAT_ARRAY_TYPE(16);
1033 var a0=axis [0], a1=axis [1], a2=axis [2];
1034 var l = Math.sqrt(a0*a0 + a1*a1 + a2*a2);
1035 var x = a0, y = a1, z = a2;
1036 if (l != 1.0) {
1037 var im = 1.0 / l;
1038 x *= im;
1039 y *= im;
1040 z *= im;
1042 var c = Math.cos(angle);
1043 var c1 = 1-c;
1044 var s = Math.sin(angle);
1045 var xs = x*s;
1046 var ys = y*s;
1047 var zs = z*s;
1048 var xyc1 = x * y * c1;
1049 var xzc1 = x * z * c1;
1050 var yzc1 = y * z * c1;
1052 var m11 = m[0];
1053 var m21 = m[1];
1054 var m31 = m[2];
1055 var m41 = m[3];
1056 var m12 = m[4];
1057 var m22 = m[5];
1058 var m32 = m[6];
1059 var m42 = m[7];
1060 var m13 = m[8];
1061 var m23 = m[9];
1062 var m33 = m[10];
1063 var m43 = m[11];
1065 var t11 = x * x * c1 + c;
1066 var t21 = xyc1 + zs;
1067 var t31 = xzc1 - ys;
1068 var t12 = xyc1 - zs;
1069 var t22 = y * y * c1 + c;
1070 var t32 = yzc1 + xs;
1071 var t13 = xzc1 + ys;
1072 var t23 = yzc1 - xs;
1073 var t33 = z * z * c1 + c;
1075 r[0] = m11 * t11 + m12 * t21 + m13 * t31;
1076 r[1] = m21 * t11 + m22 * t21 + m23 * t31;
1077 r[2] = m31 * t11 + m32 * t21 + m33 * t31;
1078 r[3] = m41 * t11 + m42 * t21 + m43 * t31;
1079 r[4] = m11 * t12 + m12 * t22 + m13 * t32;
1080 r[5] = m21 * t12 + m22 * t22 + m23 * t32;
1081 r[6] = m31 * t12 + m32 * t22 + m33 * t32;
1082 r[7] = m41 * t12 + m42 * t22 + m43 * t32;
1083 r[8] = m11 * t13 + m12 * t23 + m13 * t33;
1084 r[9] = m21 * t13 + m22 * t23 + m23 * t33;
1085 r[10] = m31 * t13 + m32 * t23 + m33 * t33;
1086 r[11] = m41 * t13 + m42 * t23 + m43 * t33;
1087 if (r != m) {
1088 r[12] = m[12];
1089 r[13] = m[13];
1090 r[14] = m[14];
1091 r[15] = m[15];
1093 return r;
1094 };
1096 /*
1097 * Function: M4x4.makeScale3
1099 * Creates a transformation matrix for scaling by 3 scalar values, one for
1100 * each of the x, y, and z directions.
1102 * Parameters:
1104 * x - the scale for the x axis
1105 * y - the scale for the y axis
1106 * z - the scale for the z axis
1107 * r - optional 4x4 matrix to store the result in
1109 * Returns:
1111 * If r is specified, returns r after creating the matrix.
1112 * Otherwise, returns a new 4x4 matrix with the result.
1113 */
1114 M4x4.makeScale3 = function M4x4_makeScale3(x, y, z, r) {
1115 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1117 if (r == undefined)
1118 r = new MJS_FLOAT_ARRAY_TYPE(16);
1120 r[0] = x;
1121 r[1] = 0;
1122 r[2] = 0;
1123 r[3] = 0;
1124 r[4] = 0;
1125 r[5] = y;
1126 r[6] = 0;
1127 r[7] = 0;
1128 r[8] = 0;
1129 r[9] = 0;
1130 r[10] = z;
1131 r[11] = 0;
1132 r[12] = 0;
1133 r[13] = 0;
1134 r[14] = 0;
1135 r[15] = 1;
1137 return r;
1138 };
1140 /*
1141 * Function: M4x4.makeScale1
1143 * Creates a transformation matrix for a uniform scale by a single scalar value.
1145 * Parameters:
1147 * k - the scale factor
1148 * r - optional 4x4 matrix to store the result in
1150 * Returns:
1152 * If r is specified, returns r after creating the matrix.
1153 * Otherwise, returns a new 4x4 matrix with the result.
1154 */
1155 M4x4.makeScale1 = function M4x4_makeScale1(k, r) {
1156 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1158 return M4x4.makeScale3(k, k, k, r);
1159 };
1161 /*
1162 * Function: M4x4.makeScale
1164 * Creates a transformation matrix for scaling each of the x, y, and z axes by the amount
1165 * given in the corresponding element of the 3-element vector.
1167 * Parameters:
1169 * v - the 3-element vector containing the scale factors
1170 * r - optional 4x4 matrix to store the result in
1172 * Returns:
1174 * If r is specified, returns r after creating the matrix.
1175 * Otherwise, returns a new 4x4 matrix with the result.
1176 */
1177 M4x4.makeScale = function M4x4_makeScale(v, r) {
1178 //MathUtils_assert(v.length == 3, "v.length == 3");
1179 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1181 return M4x4.makeScale3(v[0], v[1], v[2], r);
1182 };
1184 /*
1185 * Function: M4x4.scale3
1186 */
1187 M4x4.scale3 = function M4x4_scale3(x, y, z, m, r) {
1188 //MathUtils_assert(m.length == 16, "m.length == 16");
1189 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1191 if (r == m) {
1192 m[0] *= x;
1193 m[1] *= x;
1194 m[2] *= x;
1195 m[3] *= x;
1196 m[4] *= y;
1197 m[5] *= y;
1198 m[6] *= y;
1199 m[7] *= y;
1200 m[8] *= z;
1201 m[9] *= z;
1202 m[10] *= z;
1203 m[11] *= z;
1204 return m;
1207 if (r == undefined)
1208 r = new MJS_FLOAT_ARRAY_TYPE(16);
1210 r[0] = m[0] * x;
1211 r[1] = m[1] * x;
1212 r[2] = m[2] * x;
1213 r[3] = m[3] * x;
1214 r[4] = m[4] * y;
1215 r[5] = m[5] * y;
1216 r[6] = m[6] * y;
1217 r[7] = m[7] * y;
1218 r[8] = m[8] * z;
1219 r[9] = m[9] * z;
1220 r[10] = m[10] * z;
1221 r[11] = m[11] * z;
1222 r[12] = m[12];
1223 r[13] = m[13];
1224 r[14] = m[14];
1225 r[15] = m[15];
1227 return r;
1228 };
1230 /*
1231 * Function: M4x4.scale1
1232 */
1233 M4x4.scale1 = function M4x4_scale1(k, m, r) {
1234 //MathUtils_assert(m.length == 16, "m.length == 16");
1235 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1236 if (r == m) {
1237 m[0] *= k;
1238 m[1] *= k;
1239 m[2] *= k;
1240 m[3] *= k;
1241 m[4] *= k;
1242 m[5] *= k;
1243 m[6] *= k;
1244 m[7] *= k;
1245 m[8] *= k;
1246 m[9] *= k;
1247 m[10] *= k;
1248 m[11] *= k;
1249 return m;
1253 if (r == undefined)
1254 r = new MJS_FLOAT_ARRAY_TYPE(16);
1256 r[0] = m[0] * k;
1257 r[1] = m[1] * k;
1258 r[2] = m[2] * k;
1259 r[3] = m[3] * k;
1260 r[4] = m[4] * k;
1261 r[5] = m[5] * k;
1262 r[6] = m[6] * k;
1263 r[7] = m[7] * k;
1264 r[8] = m[8] * k;
1265 r[9] = m[9] * k;
1266 r[10] = m[10] * k;
1267 r[11] = m[11] * k;
1268 r[12] = m[12];
1269 r[13] = m[13];
1270 r[14] = m[14];
1271 r[15] = m[15];
1273 return r;
1274 };
1276 /*
1277 * Function: M4x4.scale1
1278 */
1279 M4x4.scale = function M4x4_scale(v, m, r) {
1280 //MathUtils_assert(v.length == 3, "v.length == 3");
1281 //MathUtils_assert(m.length == 16, "m.length == 16");
1282 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1283 var x = v[0], y = v[1], z = v[2];
1285 if (r == m) {
1286 m[0] *= x;
1287 m[1] *= x;
1288 m[2] *= x;
1289 m[3] *= x;
1290 m[4] *= y;
1291 m[5] *= y;
1292 m[6] *= y;
1293 m[7] *= y;
1294 m[8] *= z;
1295 m[9] *= z;
1296 m[10] *= z;
1297 m[11] *= z;
1298 return m;
1301 if (r == undefined)
1302 r = new MJS_FLOAT_ARRAY_TYPE(16);
1305 r[0] = m[0] * x;
1306 r[1] = m[1] * x;
1307 r[2] = m[2] * x;
1308 r[3] = m[3] * x;
1309 r[4] = m[4] * y;
1310 r[5] = m[5] * y;
1311 r[6] = m[6] * y;
1312 r[7] = m[7] * y;
1313 r[8] = m[8] * z;
1314 r[9] = m[9] * z;
1315 r[10] = m[10] * z;
1316 r[11] = m[11] * z;
1317 r[12] = m[12];
1318 r[13] = m[13];
1319 r[14] = m[14];
1320 r[15] = m[15];
1322 return r;
1323 };
1325 /*
1326 * Function: M4x4.makeTranslate3
1327 */
1328 M4x4.makeTranslate3 = function M4x4_makeTranslate3(x, y, z, r) {
1329 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1331 if (r == undefined)
1332 r = new MJS_FLOAT_ARRAY_TYPE(16);
1334 r[0] = 1;
1335 r[1] = 0;
1336 r[2] = 0;
1337 r[3] = 0;
1338 r[4] = 0;
1339 r[5] = 1;
1340 r[6] = 0;
1341 r[7] = 0;
1342 r[8] = 0;
1343 r[9] = 0;
1344 r[10] = 1;
1345 r[11] = 0;
1346 r[12] = x;
1347 r[13] = y;
1348 r[14] = z;
1349 r[15] = 1;
1351 return r;
1352 };
1354 /*
1355 * Function: M4x4.makeTranslate1
1356 */
1357 M4x4.makeTranslate1 = function M4x4_makeTranslate1 (k, r) {
1358 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1360 return M4x4.makeTranslate3(k, k, k, r);
1361 };
1363 /*
1364 * Function: M4x4.makeTranslate
1365 */
1366 M4x4.makeTranslate = function M4x4_makeTranslate (v, r) {
1367 //MathUtils_assert(v.length == 3, "v.length == 3");
1368 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1370 return M4x4.makeTranslate3(v[0], v[1], v[2], r);
1371 };
1373 /*
1374 * Function: M4x4.translate3Self
1375 */
1376 M4x4.translate3Self = function M4x4_translate3Self (x, y, z, m) {
1377 //MathUtils_assert(m.length == 16, "m.length == 16");
1378 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1379 m[12] += m[0] * x + m[4] * y + m[8] * z;
1380 m[13] += m[1] * x + m[5] * y + m[9] * z;
1381 m[14] += m[2] * x + m[6] * y + m[10] * z;
1382 m[15] += m[3] * x + m[7] * y + m[11] * z;
1383 return m;
1384 };
1386 /*
1387 * Function: M4x4.translate3
1388 */
1389 M4x4.translate3 = function M4x4_translate3 (x, y, z, m, r) {
1390 //MathUtils_assert(m.length == 16, "m.length == 16");
1391 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1393 if (r == m) {
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;
1398 return m;
1401 if (r == undefined)
1402 r = new MJS_FLOAT_ARRAY_TYPE(16);
1404 var m11 = m[0];
1405 var m21 = m[1];
1406 var m31 = m[2];
1407 var m41 = m[3];
1408 var m12 = m[4];
1409 var m22 = m[5];
1410 var m32 = m[6];
1411 var m42 = m[7];
1412 var m13 = m[8];
1413 var m23 = m[9];
1414 var m33 = m[10];
1415 var m43 = m[11];
1418 r[0] = m11;
1419 r[1] = m21;
1420 r[2] = m31;
1421 r[3] = m41;
1422 r[4] = m12;
1423 r[5] = m22;
1424 r[6] = m32;
1425 r[7] = m42;
1426 r[8] = m13;
1427 r[9] = m23;
1428 r[10] = m33;
1429 r[11] = m43;
1430 r[12] = m11 * x + m12 * y + m13 * z + m[12];
1431 r[13] = m21 * x + m22 * y + m23 * z + m[13];
1432 r[14] = m31 * x + m32 * y + m33 * z + m[14];
1433 r[15] = m41 * x + m42 * y + m43 * z + m[15];
1435 return r;
1436 };
1438 /*
1439 * Function: M4x4.translate1
1440 */
1441 M4x4.translate1 = function M4x4_translate1 (k, m, r) {
1442 //MathUtils_assert(m.length == 16, "m.length == 16");
1443 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1445 return M4x4.translate3(k, k, k, m, r);
1446 };
1447 /*
1448 * Function: M4x4.translateSelf
1449 */
1450 M4x4.translateSelf = function M4x4_translateSelf (v, m) {
1451 //MathUtils_assert(v.length == 3, "v.length == 3");
1452 //MathUtils_assert(m.length == 16, "m.length == 16");
1453 var x=v[0], y=v[1], z=v[2];
1454 m[12] += m[0] * x + m[4] * y + m[8] * z;
1455 m[13] += m[1] * x + m[5] * y + m[9] * z;
1456 m[14] += m[2] * x + m[6] * y + m[10] * z;
1457 m[15] += m[3] * x + m[7] * y + m[11] * z;
1458 return m;
1459 };
1460 /*
1461 * Function: M4x4.translate
1462 */
1463 M4x4.translate = function M4x4_translate (v, m, r) {
1464 //MathUtils_assert(v.length == 3, "v.length == 3");
1465 //MathUtils_assert(m.length == 16, "m.length == 16");
1466 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1467 var x=v[0], y=v[1], z=v[2];
1468 if (r == m) {
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;
1473 return m;
1476 if (r == undefined)
1477 r = new MJS_FLOAT_ARRAY_TYPE(16);
1479 var m11 = m[0];
1480 var m21 = m[1];
1481 var m31 = m[2];
1482 var m41 = m[3];
1483 var m12 = m[4];
1484 var m22 = m[5];
1485 var m32 = m[6];
1486 var m42 = m[7];
1487 var m13 = m[8];
1488 var m23 = m[9];
1489 var m33 = m[10];
1490 var m43 = m[11];
1492 r[0] = m11;
1493 r[1] = m21;
1494 r[2] = m31;
1495 r[3] = m41;
1496 r[4] = m12;
1497 r[5] = m22;
1498 r[6] = m32;
1499 r[7] = m42;
1500 r[8] = m13;
1501 r[9] = m23;
1502 r[10] = m33;
1503 r[11] = m43;
1504 r[12] = m11 * x + m12 * y + m13 * z + m[12];
1505 r[13] = m21 * x + m22 * y + m23 * z + m[13];
1506 r[14] = m31 * x + m32 * y + m33 * z + m[14];
1507 r[15] = m41 * x + m42 * y + m43 * z + m[15];
1509 return r;
1510 };
1512 /*
1513 * Function: M4x4.makeLookAt
1514 */
1515 M4x4.makeLookAt = function M4x4_makeLookAt (eye, center, up, r) {
1516 //MathUtils_assert(eye.length == 3, "eye.length == 3");
1517 //MathUtils_assert(center.length == 3, "center.length == 3");
1518 //MathUtils_assert(up.length == 3, "up.length == 3");
1519 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1521 var z = V3.direction(eye, center, V3._temp1);
1522 var x = V3.normalize(V3.cross(up, z, V3._temp2), V3._temp2);
1523 var y = V3.normalize(V3.cross(z, x, V3._temp3), V3._temp3);
1525 var tm1 = M4x4._temp1;
1526 var tm2 = M4x4._temp2;
1528 tm1[0] = x[0];
1529 tm1[1] = y[0];
1530 tm1[2] = z[0];
1531 tm1[3] = 0;
1532 tm1[4] = x[1];
1533 tm1[5] = y[1];
1534 tm1[6] = z[1];
1535 tm1[7] = 0;
1536 tm1[8] = x[2];
1537 tm1[9] = y[2];
1538 tm1[10] = z[2];
1539 tm1[11] = 0;
1540 tm1[12] = 0;
1541 tm1[13] = 0;
1542 tm1[14] = 0;
1543 tm1[15] = 1;
1545 tm2[0] = 1; tm2[1] = 0; tm2[2] = 0; tm2[3] = 0;
1546 tm2[4] = 0; tm2[5] = 1; tm2[6] = 0; tm2[7] = 0;
1547 tm2[8] = 0; tm2[9] = 0; tm2[10] = 1; tm2[11] = 0;
1548 tm2[12] = -eye[0]; tm2[13] = -eye[1]; tm2[14] = -eye[2]; tm2[15] = 1;
1550 if (r == undefined)
1551 r = new MJS_FLOAT_ARRAY_TYPE(16);
1552 return M4x4.mul(tm1, tm2, r);
1553 };
1555 /*
1556 * Function: M4x4.transposeSelf
1557 */
1558 M4x4.transposeSelf = function M4x4_transposeSelf (m) {
1559 //MathUtils_assert(m.length == 16, "m.length == 16");
1560 var tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1561 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1562 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1563 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1564 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1565 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1566 return m;
1567 };
1568 /*
1569 * Function: M4x4.transpose
1570 */
1571 M4x4.transpose = function M4x4_transpose (m, r) {
1572 //MathUtils_assert(m.length == 16, "m.length == 16");
1573 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1575 if (m == r) {
1576 var tmp = 0.0;
1577 tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1578 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1579 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1580 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1581 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1582 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1583 return m;
1586 if (r == undefined)
1587 r = new MJS_FLOAT_ARRAY_TYPE(16);
1589 r[0] = m[0]; r[1] = m[4]; r[2] = m[8]; r[3] = m[12];
1590 r[4] = m[1]; r[5] = m[5]; r[6] = m[9]; r[7] = m[13];
1591 r[8] = m[2]; r[9] = m[6]; r[10] = m[10]; r[11] = m[14];
1592 r[12] = m[3]; r[13] = m[7]; r[14] = m[11]; r[15] = m[15];
1594 return r;
1595 };
1598 /*
1599 * Function: M4x4.transformPoint
1600 */
1601 M4x4.transformPoint = function M4x4_transformPoint (m, v, r) {
1602 //MathUtils_assert(m.length == 16, "m.length == 16");
1603 //MathUtils_assert(v.length == 3, "v.length == 3");
1604 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1605 if (r == undefined)
1606 r = new MJS_FLOAT_ARRAY_TYPE(3);
1608 var v0 = v[0], v1 = v[1], v2 = v[2];
1610 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1611 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1612 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1613 var w = m[3] * v0 + m[7] * v1 + m[11] * v2 + m[15];
1615 if (w != 1.0) {
1616 r[0] /= w;
1617 r[1] /= w;
1618 r[2] /= w;
1621 return r;
1622 };
1624 /*
1625 * Function: M4x4.transformLine
1626 */
1627 M4x4.transformLine = function M4x4_transformLine(m, v, r) {
1628 //MathUtils_assert(m.length == 16, "m.length == 16");
1629 //MathUtils_assert(v.length == 3, "v.length == 3");
1630 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1631 if (r == undefined)
1632 r = new MJS_FLOAT_ARRAY_TYPE(3);
1634 var v0 = v[0], v1 = v[1], v2 = v[2];
1635 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1636 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1637 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1638 var w = m[3] * v0 + m[7] * v1 + m[11] * v2;
1640 if (w != 1.0) {
1641 r[0] /= w;
1642 r[1] /= w;
1643 r[2] /= w;
1646 return r;
1647 };
1650 /*
1651 * Function: M4x4.transformPointAffine
1652 */
1653 M4x4.transformPointAffine = function M4x4_transformPointAffine (m, v, r) {
1654 //MathUtils_assert(m.length == 16, "m.length == 16");
1655 //MathUtils_assert(v.length == 3, "v.length == 3");
1656 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1657 if (r == undefined)
1658 r = new MJS_FLOAT_ARRAY_TYPE(3);
1660 var v0 = v[0], v1 = v[1], v2 = v[2];
1662 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1663 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1664 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1666 return r;
1667 };
1669 /*
1670 * Function: M4x4.transformLineAffine
1671 */
1672 M4x4.transformLineAffine = function M4x4_transformLineAffine(m, v, r) {
1673 //MathUtils_assert(m.length == 16, "m.length == 16");
1674 //MathUtils_assert(v.length == 3, "v.length == 3");
1675 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1676 if (r == undefined)
1677 r = new MJS_FLOAT_ARRAY_TYPE(3);
1679 var v0 = v[0], v1 = v[1], v2 = v[2];
1680 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1681 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1682 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1684 return r;
1685 };
1687 M4x4.makeBasis = function M4x4_makeBasis(vx,vy,vz) {
1689 var r = new MJS_FLOAT_ARRAY_TYPE(16);
1691 r[0] = vx[0];
1692 r[1] = vx[1];
1693 r[2] = vx[2];
1694 r[3] = 0;
1695 r[4] = vy[0];
1696 r[5] = vy[1];
1697 r[6] = vy[2];
1698 r[7] = 0;
1699 r[8] = vz[0];
1700 r[9] = vz[1];
1701 r[10] = vz[2];
1702 r[11] = 0;
1703 r[12] = 0;
1704 r[13] = 0;
1705 r[14] = 0;
1706 r[15] = 1;
1708 return r;
1710 };
1712 return {
1713 V3: V3,
1714 v3: F3(V3.$),
1715 getX: V3.getX,
1716 getY: V3.getY,
1717 getZ: V3.getZ,
1718 toTuple3: V3.toTuple3,
1719 toRecord3: V3.toRecord3,
1720 fromTuple3: V3.fromTuple3,
1721 fromRecord3: V3.fromRecord3,
1722 v3add: F2(V3.add),
1723 v3sub: F2(V3.sub),
1724 v3neg: V3.neg,
1725 v3direction: F2(V3.direction),
1726 v3length: V3.length,
1727 v3lengthSquared: V3.lengthSquared,
1728 v3normalize: V3.normalize,
1729 v3scale: F2(V3.scale),
1730 v3dot: F2(V3.dot),
1731 v3cross: F2(V3.cross),
1732 v3mul4x4: F2(V3.mul4x4),
1733 M4x4:M4x4,
1734 m4x4identity: M4x4.identity,
1735 m4x4topLeft3x3: M4x4.topLeft3x3,
1736 m4x4inverseOrthonormal: M4x4.inverseOrthonormal,
1737 m4x4inverseTo3x3: M4x4.inverseTo3x3,
1738 m4x4makeFrustum: F6(M4x4.makeFrustum),
1739 m4x4makePerspective: F4(M4x4.makePerspective),
1740 m4x4makeOrtho: F6(M4x4.makeOrtho),
1741 m4x4makeOrtho2D: F4(M4x4.makeOrtho2D),
1742 m4x4mul: F2(M4x4.mul),
1743 m4x4Affine: F2(M4x4.mulAffine),
1744 m4x4makeRotate: F2(M4x4.makeRotate),
1745 m4x4rotate: F3(M4x4.rotate),
1746 m4x4makeScale3: F3(M4x4.makeScale3),
1747 m4x4makeScale1: M4x4.makeScale1,
1748 m4x4makeScale: M4x4.makeScale,
1749 m4x4scale3: F4(M4x4.scale3),
1750 m4x4scale: F2(M4x4.scale),
1751 m4x4makeTranslate3: F3(M4x4.makeTranslate3),
1752 m4x4makeTranslate: M4x4.makeTranslate,
1753 m4x4translate3: F4(M4x4.translate3),
1754 m4x4translate: F2(M4x4.translate),
1755 m4x4makeLookAt: F3(M4x4.makeLookAt),
1756 m4x4transpose: M4x4.transpose,
1757 m4x4transformPoint: F2(M4x4.transformPoint),
1758 m4x4makeBasis: F3(M4x4.makeBasis),
1759 };