on a438d56 help sign in
1923 lines 58 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 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 const 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 const MJS_DO_ASSERT = true;
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 //const MJS_FLOAT_ARRAY_TYPE = WebGLFloatArray;
72 const MJS_FLOAT_ARRAY_TYPE = Float32Array;
73 //const MJS_FLOAT_ARRAY_TYPE = Float64Array;
74 //const MJS_FLOAT_ARRAY_TYPE = Array;
76 if (MJS_DO_ASSERT) {
77 function MathUtils_assert(cond, msg) {
78 if (!cond)
79 throw "Assertion failed: " + msg;
80 }
81 } else {
82 function MathUtils_assert() { }
83 }
85 /*
86 * Class: V3
87 *
88 * Methods for working with 3-element vectors. A vector is represented by a 3-element array.
89 * Any valid JavaScript array type may be used, but if new
90 * vectors are created they are created using the configured MJS_FLOAT_ARRAY_TYPE.
91 */
93 var V3 = { };
95 V3._temp1 = new MJS_FLOAT_ARRAY_TYPE(3);
96 V3._temp2 = new MJS_FLOAT_ARRAY_TYPE(3);
97 V3._temp3 = new MJS_FLOAT_ARRAY_TYPE(3);
99 if (MJS_FLOAT_ARRAY_TYPE == Array) {
100 V3.x = [1.0, 0.0, 0.0];
101 V3.y = [0.0, 1.0, 0.0];
102 V3.z = [0.0, 0.0, 1.0];
104 V3.$ = function V3_$(x, y, z) {
105 return [x, y, z];
106 };
108 V3.clone = function V3_clone(a) {
109 //MathUtils_assert(a.length == 3, "a.length == 3");
110 return [a[0], a[1], a[2]];
111 };
112 } else {
113 V3.x = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0]);
114 V3.y = new MJS_FLOAT_ARRAY_TYPE([0.0, 1.0, 0.0]);
115 V3.z = new MJS_FLOAT_ARRAY_TYPE([0.0, 0.0, 1.0]);
117 /*
118 * Function: V3.$
119 *
120 * Creates a new 3-element vector with the given values.
121 *
122 * Parameters:
123 *
124 * x,y,z - the 3 elements of the new vector.
125 *
126 * Returns:
127 *
128 * A new vector containing with the given argument values.
129 */
131 V3.$ = function V3_$(x, y, z) {
132 return new MJS_FLOAT_ARRAY_TYPE([x, y, z]);
133 };
135 /*
136 * Function: V3.clone
137 *
138 * Clone the given 3-element vector.
139 *
140 * Parameters:
141 *
142 * a - the 3-element vector to clone
143 *
144 * Returns:
145 *
146 * A new vector with the same values as the passed-in one.
147 */
149 V3.clone = function V3_clone(a) {
150 //MathUtils_assert(a.length == 3, "a.length == 3");
151 return new MJS_FLOAT_ARRAY_TYPE(a);
152 };
153 }
155 V3.u = V3.x;
156 V3.v = V3.y;
158 /*
159 * Function: V3.add
160 *
161 * Perform r = a + b.
162 *
163 * Parameters:
164 *
165 * a - the first vector operand
166 * b - the second vector operand
167 * r - optional vector to store the result in
168 *
169 * Returns:
170 *
171 * If r is specified, returns r after performing the operation.
172 * Otherwise, returns a new 3-element vector with the result.
173 */
174 V3.add = function V3_add(a, b, r) {
175 //MathUtils_assert(a.length == 3, "a.length == 3");
176 //MathUtils_assert(b.length == 3, "b.length == 3");
177 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
179 if (r == undefined)
180 r = new MJS_FLOAT_ARRAY_TYPE(3);
181 r[0] = a[0] + b[0];
182 r[1] = a[1] + b[1];
183 r[2] = a[2] + b[2];
184 return r;
185 };
187 /*
188 * Function: V3.sub
189 *
190 * Perform
191 * r = a - b.
192 *
193 * Parameters:
194 *
195 * a - the first vector operand
196 * b - the second vector operand
197 * r - optional vector to store the result in
198 *
199 * Returns:
200 *
201 * If r is specified, returns r after performing the operation.
202 * Otherwise, returns a new 3-element vector with the result.
203 */
204 V3.sub = function V3_sub(a, b, r) {
205 //MathUtils_assert(a.length == 3, "a.length == 3");
206 //MathUtils_assert(b.length == 3, "b.length == 3");
207 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
209 if (r == undefined)
210 r = new MJS_FLOAT_ARRAY_TYPE(3);
211 r[0] = a[0] - b[0];
212 r[1] = a[1] - b[1];
213 r[2] = a[2] - b[2];
214 return r;
215 };
217 /*
218 * Function: V3.neg
219 *
220 * Perform
221 * r = - a.
222 *
223 * Parameters:
224 *
225 * a - the vector operand
226 * r - optional vector to store the result in
227 *
228 * Returns:
229 *
230 * If r is specified, returns r after performing the operation.
231 * Otherwise, returns a new 3-element vector with the result.
232 */
233 V3.neg = function V3_neg(a, r) {
234 //MathUtils_assert(a.length == 3, "a.length == 3");
235 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
237 if (r == undefined)
238 r = new MJS_FLOAT_ARRAY_TYPE(3);
239 r[0] = - a[0];
240 r[1] = - a[1];
241 r[2] = - a[2];
242 return r;
243 };
245 /*
246 * Function: V3.direction
247 *
248 * Perform
249 * r = (a - b) / |a - b|. The result is the normalized
250 * direction from a to b.
251 *
252 * Parameters:
253 *
254 * a - the first vector operand
255 * b - the second vector operand
256 * r - optional vector to store the result in
257 *
258 * Returns:
259 *
260 * If r is specified, returns r after performing the operation.
261 * Otherwise, returns a new 3-element vector with the result.
262 */
263 V3.direction = function V3_direction(a, b, r) {
264 //MathUtils_assert(a.length == 3, "a.length == 3");
265 //MathUtils_assert(b.length == 3, "b.length == 3");
266 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
268 if (r == undefined)
269 r = new MJS_FLOAT_ARRAY_TYPE(3);
270 return V3.normalize(V3.sub(a, b, r), r);
271 };
273 /*
274 * Function: V3.length
275 *
276 * Perform r = |a|.
277 *
278 * Parameters:
279 *
280 * a - the vector operand
281 *
282 * Returns:
283 *
284 * The length of the given vector.
285 */
286 V3.length = function V3_length(a) {
287 //MathUtils_assert(a.length == 3, "a.length == 3");
289 return Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
290 };
292 /*
293 * Function: V3.lengthSquard
294 *
295 * Perform r = |a|*|a|.
296 *
297 * Parameters:
298 *
299 * a - the vector operand
300 *
301 * Returns:
302 *
303 * The square of the length of the given vector.
304 */
305 V3.lengthSquared = function V3_lengthSquared(a) {
306 //MathUtils_assert(a.length == 3, "a.length == 3");
308 return a[0]*a[0] + a[1]*a[1] + a[2]*a[2];
309 };
311 /*
312 * Function: V3.normalize
313 *
314 * Perform r = a / |a|.
315 *
316 * Parameters:
317 *
318 * a - the vector operand
319 * r - optional vector to store the result in
320 *
321 * Returns:
322 *
323 * If r is specified, returns r after performing the operation.
324 * Otherwise, returns a new 3-element vector with the result.
325 */
326 V3.normalize = function V3_normalize(a, r) {
327 //MathUtils_assert(a.length == 3, "a.length == 3");
328 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
330 if (r == undefined)
331 r = new MJS_FLOAT_ARRAY_TYPE(3);
332 var im = 1.0 / V3.length(a);
333 r[0] = a[0] * im;
334 r[1] = a[1] * im;
335 r[2] = a[2] * im;
336 return r;
337 };
339 /*
340 * Function: V3.scale
341 *
342 * Perform r = a * k.
343 *
344 * Parameters:
345 *
346 * a - the vector operand
347 * k - a scalar value
348 * r - optional vector to store the result in
349 *
350 * Returns:
351 *
352 * If r is specified, returns r after performing the operation.
353 * Otherwise, returns a new 3-element vector with the result.
354 */
355 V3.scale = function V3_scale(a, k, r) {
356 //MathUtils_assert(a.length == 3, "a.length == 3");
357 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
359 if (r == undefined)
360 r = new MJS_FLOAT_ARRAY_TYPE(3);
361 r[0] = a[0] * k;
362 r[1] = a[1] * k;
363 r[2] = a[2] * k;
364 return r;
365 };
367 /*
368 * Function: V3.dot
369 *
370 * Perform
371 * r = dot(a, b).
372 *
373 * Parameters:
374 *
375 * a - the first vector operand
376 * b - the second vector operand
377 *
378 * Returns:
379 *
380 * The dot product of a and b.
381 */
382 V3.dot = function V3_dot(a, b) {
383 //MathUtils_assert(a.length == 3, "a.length == 3");
384 //MathUtils_assert(b.length == 3, "b.length == 3");
386 return a[0] * b[0] +
387 a[1] * b[1] +
388 a[2] * b[2];
389 };
391 /*
392 * Function: V3.cross
393 *
394 * Perform r = a x b.
395 *
396 * Parameters:
397 *
398 * a - the first vector operand
399 * b - the second vector operand
400 * r - optional vector to store the result in
401 *
402 * Returns:
403 *
404 * If r is specified, returns r after performing the operation.
405 * Otherwise, returns a new 3-element vector with the result.
406 */
407 V3.cross = function V3_cross(a, b, r) {
408 //MathUtils_assert(a.length == 3, "a.length == 3");
409 //MathUtils_assert(b.length == 3, "b.length == 3");
410 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
412 if (r == undefined)
413 r = new MJS_FLOAT_ARRAY_TYPE(3);
414 r[0] = a[1]*b[2] - a[2]*b[1];
415 r[1] = a[2]*b[0] - a[0]*b[2];
416 r[2] = a[0]*b[1] - a[1]*b[0];
417 return r;
418 };
420 /*
421 * Function: V3.mul4x4
422 *
423 * Perform
424 * r = m * v.
425 *
426 * Parameters:
427 *
428 * m - the 4x4 matrix operand
429 * v - the 3-element vector operand
430 * r - optional vector to store the result in
431 *
432 * Returns:
433 *
434 * If r is specified, returns r after performing the operation.
435 * Otherwise, returns a new 3-element vector with the result.
436 * The 4-element result vector is divided by the w component
437 * and returned as a 3-element vector.
438 */
439 V3.mul4x4 = function V3_mul4x4(m, v, r) {
440 //MathUtils_assert(m.length == 16, "m.length == 16");
441 //MathUtils_assert(v.length == 3, "v.length == 3");
442 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
444 var w;
445 var tmp = V3._temp1;
446 if (r == undefined)
447 r = new MJS_FLOAT_ARRAY_TYPE(3);
448 tmp[0] = m[ 3];
449 tmp[1] = m[ 7];
450 tmp[2] = m[11];
451 w = V3.dot(v, tmp) + m[15];
452 tmp[0] = m[ 0];
453 tmp[1] = m[ 4];
454 tmp[2] = m[ 8];
455 r[0] = (V3.dot(v, tmp) + m[12])/w;
456 tmp[0] = m[ 1];
457 tmp[1] = m[ 5];
458 tmp[2] = m[ 9];
459 r[1] = (V3.dot(v, tmp) + m[13])/w;
460 tmp[0] = m[ 2];
461 tmp[1] = m[ 6];
462 tmp[2] = m[10];
463 r[2] = (V3.dot(v, tmp) + m[14])/w;
464 return r;
465 };
467 /*
468 * Class: M4x4
469 *
470 * Methods for working with 4x4 matrices. A matrix is represented by a 16-element array
471 * in column-major order. Any valid JavaScript array type may be used, but if new
472 * matrices are created they are created using the configured MJS_FLOAT_ARRAY_TYPE.
473 */
475 var M4x4 = { };
477 M4x4._temp1 = new MJS_FLOAT_ARRAY_TYPE(16);
478 M4x4._temp2 = new MJS_FLOAT_ARRAY_TYPE(16);
480 if (MJS_FLOAT_ARRAY_TYPE == Array) {
481 M4x4.I = [1.0, 0.0, 0.0, 0.0,
482 0.0, 1.0, 0.0, 0.0,
483 0.0, 0.0, 1.0, 0.0,
484 0.0, 0.0, 0.0, 1.0];
486 M4x4.$ = function M4x4_$(m00, m01, m02, m03,
487 m04, m05, m06, m07,
488 m08, m09, m10, m11,
489 m12, m13, m14, m15)
490 {
491 return [m00, m01, m02, m03,
492 m04, m05, m06, m07,
493 m08, m09, m10, m11,
494 m12, m13, m14, m15];
495 };
497 M4x4.clone = function M4x4_clone(m) {
498 //MathUtils_assert(m.length == 16, "m.length == 16");
499 return new [m[0], m[1], m[2], m[3],
500 m[4], m[5], m[6], m[7],
501 m[8], m[9], m[10], m[11],
502 m[12], m[13], m[14], m[15]];
503 };
504 } else {
505 M4x4.I = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0, 0.0,
506 0.0, 1.0, 0.0, 0.0,
507 0.0, 0.0, 1.0, 0.0,
508 0.0, 0.0, 0.0, 1.0]);
510 /*
511 * Function: M4x4.$
512 *
513 * Creates a new 4x4 matrix with the given values.
514 *
515 * Parameters:
516 *
517 * m00..m15 - the 16 elements of the new matrix.
518 *
519 * Returns:
520 *
521 * A new matrix filled with the given argument values.
522 */
523 M4x4.$ = function M4x4_$(m00, m01, m02, m03,
524 m04, m05, m06, m07,
525 m08, m09, m10, m11,
526 m12, m13, m14, m15)
527 {
528 return new MJS_FLOAT_ARRAY_TYPE([m00, m01, m02, m03,
529 m04, m05, m06, m07,
530 m08, m09, m10, m11,
531 m12, m13, m14, m15]);
532 };
534 /*
535 * Function: M4x4.clone
536 *
537 * Clone the given 4x4 matrix.
538 *
539 * Parameters:
540 *
541 * m - the 4x4 matrix to clone
542 *
543 * Returns:
544 *
545 * A new matrix with the same values as the passed-in one.
546 */
547 M4x4.clone = function M4x4_clone(m) {
548 //MathUtils_assert(m.length == 16, "m.length == 16");
549 return new MJS_FLOAT_ARRAY_TYPE(m);
550 };
551 }
553 M4x4.identity = M4x4.I;
555 /*
556 * Function: M4x4.topLeft3x3
557 *
558 * Return the top left 3x3 matrix from the given 4x4 matrix m.
559 *
560 * Parameters:
561 *
562 * m - the matrix
563 * r - optional 3x3 matrix to store the result in
564 *
565 * Returns:
566 *
567 * If r is specified, returns r after performing the operation.
568 * Otherwise, returns a new 3x3 matrix with the result.
569 */
570 M4x4.topLeft3x3 = function M4x4_topLeft3x3(m, r) {
571 //MathUtils_assert(m.length == 16, "m.length == 16");
572 //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
574 if (r == undefined)
575 r = new MJS_FLOAT_ARRAY_TYPE(9);
576 r[0] = m[0]; r[1] = m[1]; r[2] = m[2];
577 r[3] = m[4]; r[4] = m[5]; r[5] = m[6];
578 r[6] = m[8]; r[7] = m[9]; r[8] = m[10];
579 return r;
580 };
582 /*
583 * Function: M4x4.inverseOrthonormal
584 *
585 * Computes the inverse of the given matrix m, assuming that
586 * the matrix is orthonormal.
587 *
588 * Parameters:
589 *
590 * m - the matrix
591 * r - optional 4x4 matrix to store the result in
592 *
593 * Returns:
594 *
595 * If r is specified, returns r after performing the operation.
596 * Otherwise, returns a new 4x4 matrix with the result.
597 */
598 M4x4.inverseOrthonormal = function M4x4_inverseOrthonormal(m, r) {
599 //MathUtils_assert(m.length == 16, "m.length == 16");
600 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
601 //MathUtils_assert(m != r, "m != r");
603 if (r == undefined)
604 r = new MJS_FLOAT_ARRAY_TYPE(16);
605 M4x4.transpose(m, r);
606 var t = [m[12], m[13], m[14]];
607 r[3] = r[7] = r[11] = 0;
608 r[12] = -V3.dot([r[0], r[4], r[8]], t);
609 r[13] = -V3.dot([r[1], r[5], r[9]], t);
610 r[14] = -V3.dot([r[2], r[6], r[10]], t);
611 return r;
612 };
614 /*
615 * Function: M4x4.inverseTo3x3
616 *
617 * Computes the inverse of the given matrix m, but calculates
618 * only the top left 3x3 values of the result.
619 *
620 * Parameters:
621 *
622 * m - the matrix
623 * r - optional 3x3 matrix to store the result in
624 *
625 * Returns:
626 *
627 * If r is specified, returns r after performing the operation.
628 * Otherwise, returns a new 3x3 matrix with the result.
629 */
630 M4x4.inverseTo3x3 = function M4x4_inverseTo3x3(m, r) {
631 //MathUtils_assert(m.length == 16, "m.length == 16");
632 //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
634 if (r == undefined)
635 r = new MJS_FLOAT_ARRAY_TYPE(9);
637 var a11 = m[10]*m[5]-m[6]*m[9],
638 a21 = -m[10]*m[1]+m[2]*m[9],
639 a31 = m[6]*m[1]-m[2]*m[5],
640 a12 = -m[10]*m[4]+m[6]*m[8],
641 a22 = m[10]*m[0]-m[2]*m[8],
642 a32 = -m[6]*m[0]+m[2]*m[4],
643 a13 = m[9]*m[4]-m[5]*m[8],
644 a23 = -m[9]*m[0]+m[1]*m[8],
645 a33 = m[5]*m[0]-m[1]*m[4];
646 var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13);
647 if (det == 0) // no inverse
648 throw "matrix not invertible";
649 var idet = 1.0 / det;
651 r[0] = idet*a11;
652 r[1] = idet*a21;
653 r[2] = idet*a31;
654 r[3] = idet*a12;
655 r[4] = idet*a22;
656 r[5] = idet*a32;
657 r[6] = idet*a13;
658 r[7] = idet*a23;
659 r[8] = idet*a33;
661 return r;
662 };
664 /*
665 * Function: M4x4.makeFrustum
666 *
667 * Creates a matrix for a projection frustum with the given parameters.
668 *
669 * Parameters:
670 *
671 * left - the left coordinate of the frustum
672 * right- the right coordinate of the frustum
673 * bottom - the bottom coordinate of the frustum
674 * top - the top coordinate of the frustum
675 * znear - the near z distance of the frustum
676 * zfar - the far z distance of the frustum
677 * r - optional 4x4 matrix to store the result in
678 *
679 * Returns:
680 *
681 * If r is specified, returns r after creating the projection matrix.
682 * Otherwise, returns a new 4x4 matrix.
683 */
684 M4x4.makeFrustum = function M4x4_makeFrustum(left, right, bottom, top, znear, zfar, r) {
685 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
687 if (r == undefined)
688 r = new MJS_FLOAT_ARRAY_TYPE(16);
690 var X = 2*znear/(right-left);
691 var Y = 2*znear/(top-bottom);
692 var A = (right+left)/(right-left);
693 var B = (top+bottom)/(top-bottom);
694 var C = -(zfar+znear)/(zfar-znear);
695 var D = -2*zfar*znear/(zfar-znear);
697 r[0] = 2*znear/(right-left);
698 r[1] = 0;
699 r[2] = 0;
700 r[3] = 0;
701 r[4] = 0;
702 r[5] = 2*znear/(top-bottom);
703 r[6] = 0;
704 r[7] = 0;
705 r[8] = (right+left)/(right-left);
706 r[9] = (top+bottom)/(top-bottom);
707 r[10] = -(zfar+znear)/(zfar-znear);
708 r[11] = -1;
709 r[12] = 0;
710 r[13] = 0;
711 r[14] = -2*zfar*znear/(zfar-znear);
712 r[15] = 0;
714 return r;
715 };
717 /*
718 * Function: M4x4.makePerspective
719 *
720 * Creates a matrix for a perspective projection with the given parameters.
721 *
722 * Parameters:
723 *
724 * fovy - field of view in the y axis, in degrees
725 * aspect - aspect ratio
726 * znear - the near z distance of the projection
727 * zfar - the far z distance of the projection
728 * r - optional 4x4 matrix to store the result in
729 *
730 * Returns:
731 *
732 * If r is specified, returns r after creating the projection matrix.
733 * Otherwise, returns a new 4x4 matrix.
734 */
735 M4x4.makePerspective = function M4x4_makePerspective (fovy, aspect, znear, zfar, r) {
736 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
738 var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
739 var ymin = -ymax;
740 var xmin = ymin * aspect;
741 var xmax = ymax * aspect;
743 return M4x4.makeFrustum(xmin, xmax, ymin, ymax, znear, zfar, r);
744 };
746 /*
747 * Function: M4x4.makeOrtho
748 *
749 * Creates a matrix for an orthogonal frustum projection with the given parameters.
750 *
751 * Parameters:
752 *
753 * left - the left coordinate of the frustum
754 * right- the right coordinate of the frustum
755 * bottom - the bottom coordinate of the frustum
756 * top - the top coordinate of the frustum
757 * znear - the near z distance of the frustum
758 * zfar - the far z distance of the frustum
759 * r - optional 4x4 matrix to store the result in
760 *
761 * Returns:
762 *
763 * If r is specified, returns r after creating the projection matrix.
764 * Otherwise, returns a new 4x4 matrix.
765 */
766 M4x4.makeOrtho = function M4x4_makeOrtho (left, right, bottom, top, znear, zfar, r) {
767 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
769 if (r == undefined)
770 r = new MJS_FLOAT_ARRAY_TYPE(16);
772 var tX = -(right+left)/(right-left);
773 var tY = -(top+bottom)/(top-bottom);
774 var tZ = -(zfar+znear)/(zfar-znear);
775 var X = 2 / (right-left);
776 var Y = 2 / (top-bottom);
777 var Z = -2 / (zfar-znear);
779 r[0] = 2 / (right-left);
780 r[1] = 0;
781 r[2] = 0;
782 r[3] = 0;
783 r[4] = 0;
784 r[5] = 2 / (top-bottom);
785 r[6] = 0;
786 r[7] = 0;
787 r[8] = 0;
788 r[9] = 0;
789 r[10] = -2 / (zfar-znear);
790 r[11] = 0;
791 r[12] = -(right+left)/(right-left);
792 r[13] = -(top+bottom)/(top-bottom);
793 r[14] = -(zfar+znear)/(zfar-znear);
794 r[15] = 1;
796 return r;
797 };
799 /*
800 * Function: M4x4.makeOrtho
801 *
802 * Creates a matrix for a 2D orthogonal frustum projection with the given parameters.
803 * znear and zfar are assumed to be -1 and 1, respectively.
804 *
805 * Parameters:
806 *
807 * left - the left coordinate of the frustum
808 * right- the right coordinate of the frustum
809 * bottom - the bottom coordinate of the frustum
810 * top - the top coordinate of the frustum
811 * r - optional 4x4 matrix to store the result in
812 *
813 * Returns:
814 *
815 * If r is specified, returns r after creating the projection matrix.
816 * Otherwise, returns a new 4x4 matrix.
817 */
818 M4x4.makeOrtho2D = function M4x4_makeOrtho2D (left, right, bottom, top, r) {
819 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
821 return M4x4.makeOrtho(left, right, bottom, top, -1, 1, r);
822 };
824 /*
825 * Function: M4x4.mul
826 *
827 * Performs r = a * b.
828 *
829 * Parameters:
830 *
831 * a - the first matrix operand
832 * b - the second matrix operand
833 * r - optional 4x4 matrix to store the result in
834 *
835 * Returns:
836 *
837 * If r is specified, returns r after performing the operation.
838 * Otherwise, returns a new 4x4 matrix with the result.
839 */
840 M4x4.mul = function M4x4_mul(a, b, r) {
841 //MathUtils_assert(a.length == 16, "a.length == 16");
842 //MathUtils_assert(b.length == 16, "b.length == 16");
843 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
844 //MathUtils_assert(a != r && b != r, "a != r && b != r");
846 if (r == undefined)
847 r = new MJS_FLOAT_ARRAY_TYPE(16);
849 var a11 = a[0];
850 var a21 = a[1];
851 var a31 = a[2];
852 var a41 = a[3];
853 var a12 = a[4];
854 var a22 = a[5];
855 var a32 = a[6];
856 var a42 = a[7];
857 var a13 = a[8];
858 var a23 = a[9];
859 var a33 = a[10];
860 var a43 = a[11];
861 var a14 = a[12];
862 var a24 = a[13];
863 var a34 = a[14];
864 var a44 = a[15];
866 var b11 = b[0];
867 var b21 = b[1];
868 var b31 = b[2];
869 var b41 = b[3];
870 var b12 = b[4];
871 var b22 = b[5];
872 var b32 = b[6];
873 var b42 = b[7];
874 var b13 = b[8];
875 var b23 = b[9];
876 var b33 = b[10];
877 var b43 = b[11];
878 var b14 = b[12];
879 var b24 = b[13];
880 var b34 = b[14];
881 var b44 = b[15];
883 r[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
884 r[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
885 r[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
886 r[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
887 r[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
888 r[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
889 r[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
890 r[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
891 r[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
892 r[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
893 r[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
894 r[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
895 r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
896 r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
897 r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
898 r[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
900 return r;
901 };
903 /*
904 * Function: M4x4.mulOffset
905 *
906 * Performs r' = a * b, where r' is the 16 elements of r starting at element o.
907 *
908 * Parameters:
909 *
910 * a - the first matrix operand
911 * b - the second matrix operand
912 * r - array to store the result in
913 * o - offset into r at which to start storing results
914 *
915 * Returns:
916 *
917 * r
918 */
919 M4x4.mulOffset = function M4x4_mulOffset(a, b, r, o) {
920 //MathUtils_assert(a.length == 16, "a.length == 16");
921 //MathUtils_assert(b.length == 16, "b.length == 16");
923 var a21 = a[1];
924 var a31 = a[2];
925 var a41 = a[3];
926 var a12 = a[4];
927 var a22 = a[5];
928 var a32 = a[6];
929 var a42 = a[7];
930 var a13 = a[8];
931 var a23 = a[9];
932 var a33 = a[10];
933 var a43 = a[11];
934 var a14 = a[12];
935 var a24 = a[13];
936 var a34 = a[14];
937 var a44 = a[15];
939 var b11 = b[0];
940 var b21 = b[1];
941 var b31 = b[2];
942 var b41 = b[3];
943 var b12 = b[4];
944 var b22 = b[5];
945 var b32 = b[6];
946 var b42 = b[7];
947 var b13 = b[8];
948 var b23 = b[9];
949 var b33 = b[10];
950 var b43 = b[11];
951 var b14 = b[12];
952 var b24 = b[13];
953 var b34 = b[14];
954 var b44 = b[15];
956 r[o+0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
957 r[o+1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
958 r[o+2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
959 r[o+3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
960 r[o+4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
961 r[o+5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
962 r[o+6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
963 r[o+7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
964 r[o+8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
965 r[o+9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
966 r[o+10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
967 r[o+11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
968 r[o+12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
969 r[o+13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
970 r[o+14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
971 r[o+15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
973 return r;
974 };
976 /*
977 * Function: M4x4.mulAffine
978 *
979 * Performs r = a * b, assuming a and b are affine (elements 3,7,11,15 = 0,0,0,1)
980 *
981 * Parameters:
982 *
983 * a - the first matrix operand
984 * b - the second matrix operand
985 * r - optional 4x4 matrix to store the result in
986 *
987 * Returns:
988 *
989 * If r is specified, returns r after performing the operation.
990 * Otherwise, returns a new 4x4 matrix with the result.
991 */
992 M4x4.mulAffine = function M4x4_mulAffine(a, b, r) {
993 //MathUtils_assert(a.length == 16, "a.length == 16");
994 //MathUtils_assert(b.length == 16, "b.length == 16");
995 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
996 //MathUtils_assert(a != r && b != r, "a != r && b != r");
998 if (r == undefined)
999 r = new MJS_FLOAT_ARRAY_TYPE(16);
1000 var a11 = a[0];
1001 var a21 = a[1];
1002 var a31 = a[2];
1003 var a12 = a[4];
1004 var a22 = a[5];
1005 var a32 = a[6];
1006 var a13 = a[8];
1007 var a23 = a[9];
1008 var a33 = a[10];
1009 var a14 = a[12];
1010 var a24 = a[13];
1011 var a34 = a[14];
1013 var b11 = b[0];
1014 var b21 = b[1];
1015 var b31 = b[2];
1016 var b12 = b[4];
1017 var b22 = b[5];
1018 var b32 = b[6];
1019 var b13 = b[8];
1020 var b23 = b[9];
1021 var b33 = b[10];
1022 var b14 = b[12];
1023 var b24 = b[13];
1024 var b34 = b[14];
1026 r[0] = a11 * b11 + a12 * b21 + a13 * b31;
1027 r[1] = a21 * b11 + a22 * b21 + a23 * b31;
1028 r[2] = a31 * b11 + a32 * b21 + a33 * b31;
1029 r[3] = 0;
1030 r[4] = a11 * b12 + a12 * b22 + a13 * b32;
1031 r[5] = a21 * b12 + a22 * b22 + a23 * b32;
1032 r[6] = a31 * b12 + a32 * b22 + a33 * b32;
1033 r[7] = 0;
1034 r[8] = a11 * b13 + a12 * b23 + a13 * b33;
1035 r[9] = a21 * b13 + a22 * b23 + a23 * b33;
1036 r[10] = a31 * b13 + a32 * b23 + a33 * b33;
1037 r[11] = 0;
1038 r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14;
1039 r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24;
1040 r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34;
1041 r[15] = 1;
1043 return r;
1044 };
1046 /*
1047 * Function: M4x4.mulAffineOffset
1049 * Performs r' = a * b, assuming a and b are affine (elements 3,7,11,15 = 0,0,0,1), where r' is the 16 elements of r starting at element o
1051 * Parameters:
1053 * a - the first matrix operand
1054 * b - the second matrix operand
1055 * r - array to store the result in
1056 * o - offset into r at which to start storing results
1058 * Returns:
1060 * r
1061 */
1062 M4x4.mulAffine = function M4x4_mulAffine(a, b, r, o) {
1063 //MathUtils_assert(a.length == 16, "a.length == 16");
1064 //MathUtils_assert(b.length == 16, "b.length == 16");
1066 if (r == undefined)
1067 r = new MJS_FLOAT_ARRAY_TYPE(16);
1068 var a11 = a[0];
1069 var a21 = a[1];
1070 var a31 = a[2];
1071 var a12 = a[4];
1072 var a22 = a[5];
1073 var a32 = a[6];
1074 var a13 = a[8];
1075 var a23 = a[9];
1076 var a33 = a[10];
1077 var a14 = a[12];
1078 var a24 = a[13];
1079 var a34 = a[14];
1081 var b11 = b[0];
1082 var b21 = b[1];
1083 var b31 = b[2];
1084 var b12 = b[4];
1085 var b22 = b[5];
1086 var b32 = b[6];
1087 var b13 = b[8];
1088 var b23 = b[9];
1089 var b33 = b[10];
1090 var b14 = b[12];
1091 var b24 = b[13];
1092 var b34 = b[14];
1094 r[o+0] = a11 * b11 + a12 * b21 + a13 * b31;
1095 r[o+1] = a21 * b11 + a22 * b21 + a23 * b31;
1096 r[o+2] = a31 * b11 + a32 * b21 + a33 * b31;
1097 r[o+3] = 0;
1098 r[o+4] = a11 * b12 + a12 * b22 + a13 * b32;
1099 r[o+5] = a21 * b12 + a22 * b22 + a23 * b32;
1100 r[o+6] = a31 * b12 + a32 * b22 + a33 * b32;
1101 r[o+7] = 0;
1102 r[o+8] = a11 * b13 + a12 * b23 + a13 * b33;
1103 r[o+9] = a21 * b13 + a22 * b23 + a23 * b33;
1104 r[o+10] = a31 * b13 + a32 * b23 + a33 * b33;
1105 r[o+11] = 0;
1106 r[o+12] = a11 * b14 + a12 * b24 + a13 * b34 + a14;
1107 r[o+13] = a21 * b14 + a22 * b24 + a23 * b34 + a24;
1108 r[o+14] = a31 * b14 + a32 * b24 + a33 * b34 + a34;
1109 r[o+15] = 1;
1111 return r;
1112 };
1114 /*
1115 * Function: M4x4.makeRotate
1117 * Creates a transformation matrix for rotation by angle radians about the 3-element vector axis.
1119 * Parameters:
1121 * angle - the angle of rotation, in radians
1122 * axis - the axis around which the rotation is performed, a 3-element vector
1123 * r - optional 4x4 matrix to store the result in
1125 * Returns:
1127 * If r is specified, returns r after creating the matrix.
1128 * Otherwise, returns a new 4x4 matrix with the result.
1129 */
1130 M4x4.makeRotate = function M4x4_makeRotate(angle, axis, r) {
1131 //MathUtils_assert(angle.length == 3, "angle.length == 3");
1132 //MathUtils_assert(axis.length == 3, "axis.length == 3");
1133 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1135 if (r == undefined)
1136 r = new MJS_FLOAT_ARRAY_TYPE(16);
1138 axis = V3.normalize(axis, V3._temp1);
1139 var x = axis[0], y = axis[1], z = axis[2];
1140 var c = Math.cos(angle);
1141 var c1 = 1-c;
1142 var s = Math.sin(angle);
1144 r[0] = x*x*c1+c;
1145 r[1] = y*x*c1+z*s;
1146 r[2] = z*x*c1-y*s;
1147 r[3] = 0;
1148 r[4] = x*y*c1-z*s;
1149 r[5] = y*y*c1+c;
1150 r[6] = y*z*c1+x*s;
1151 r[7] = 0;
1152 r[8] = x*z*c1+y*s;
1153 r[9] = y*z*c1-x*s;
1154 r[10] = z*z*c1+c;
1155 r[11] = 0;
1156 r[12] = 0;
1157 r[13] = 0;
1158 r[14] = 0;
1159 r[15] = 1;
1161 return r;
1162 };
1164 /*
1165 * Function: M4x4.rotate
1167 * Concatenates a rotation of angle radians about the axis to the give matrix m.
1169 * Parameters:
1171 * angle - the angle of rotation, in radians
1172 * axis - the axis around which the rotation is performed, a 3-element vector
1173 * m - the matrix to concatenate the rotation to
1174 * r - optional 4x4 matrix to store the result in
1176 * Returns:
1178 * If r is specified, returns r after performing the operation.
1179 * Otherwise, returns a new 4x4 matrix with the result.
1180 */
1181 M4x4.rotate = function M4x4_rotate(angle, axis, m, r) {
1182 //MathUtils_assert(angle.length == 3, "angle.length == 3");
1183 //MathUtils_assert(axis.length == 3, "axis.length == 3");
1184 //MathUtils_assert(m.length == 16, "m.length == 16");
1185 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1187 if (r == undefined)
1188 r = new MJS_FLOAT_ARRAY_TYPE(16);
1189 var a0=axis [0], a1=axis [1], a2=axis [2];
1190 var l = Math.sqrt(a0*a0 + a1*a1 + a2*a2);
1191 var x = a0, y = a1, z = a2;
1192 if (l != 1.0) {
1193 var im = 1.0 / l;
1194 x *= im;
1195 y *= im;
1196 z *= im;
1198 var c = Math.cos(angle);
1199 var c1 = 1-c;
1200 var s = Math.sin(angle);
1201 var xs = x*s;
1202 var ys = y*s;
1203 var zs = z*s;
1204 var xyc1 = x * y * c1;
1205 var xzc1 = x * z * c1;
1206 var yzc1 = y * z * c1;
1208 var m11 = m[0];
1209 var m21 = m[1];
1210 var m31 = m[2];
1211 var m41 = m[3];
1212 var m12 = m[4];
1213 var m22 = m[5];
1214 var m32 = m[6];
1215 var m42 = m[7];
1216 var m13 = m[8];
1217 var m23 = m[9];
1218 var m33 = m[10];
1219 var m43 = m[11];
1221 var t11 = x * x * c1 + c;
1222 var t21 = xyc1 + zs;
1223 var t31 = xzc1 - ys;
1224 var t12 = xyc1 - zs;
1225 var t22 = y * y * c1 + c;
1226 var t32 = yzc1 + xs;
1227 var t13 = xzc1 + ys;
1228 var t23 = yzc1 - xs;
1229 var t33 = z * z * c1 + c;
1231 r[0] = m11 * t11 + m12 * t21 + m13 * t31;
1232 r[1] = m21 * t11 + m22 * t21 + m23 * t31;
1233 r[2] = m31 * t11 + m32 * t21 + m33 * t31;
1234 r[3] = m41 * t11 + m42 * t21 + m43 * t31;
1235 r[4] = m11 * t12 + m12 * t22 + m13 * t32;
1236 r[5] = m21 * t12 + m22 * t22 + m23 * t32;
1237 r[6] = m31 * t12 + m32 * t22 + m33 * t32;
1238 r[7] = m41 * t12 + m42 * t22 + m43 * t32;
1239 r[8] = m11 * t13 + m12 * t23 + m13 * t33;
1240 r[9] = m21 * t13 + m22 * t23 + m23 * t33;
1241 r[10] = m31 * t13 + m32 * t23 + m33 * t33;
1242 r[11] = m41 * t13 + m42 * t23 + m43 * t33;
1243 if (r != m) {
1244 r[12] = m[12];
1245 r[13] = m[13];
1246 r[14] = m[14];
1247 r[15] = m[15];
1249 return r;
1250 };
1252 /*
1253 * Function: M4x4.makeScale3
1255 * Creates a transformation matrix for scaling by 3 scalar values, one for
1256 * each of the x, y, and z directions.
1258 * Parameters:
1260 * x - the scale for the x axis
1261 * y - the scale for the y axis
1262 * z - the scale for the z axis
1263 * r - optional 4x4 matrix to store the result in
1265 * Returns:
1267 * If r is specified, returns r after creating the matrix.
1268 * Otherwise, returns a new 4x4 matrix with the result.
1269 */
1270 M4x4.makeScale3 = function M4x4_makeScale3(x, y, z, r) {
1271 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1273 if (r == undefined)
1274 r = new MJS_FLOAT_ARRAY_TYPE(16);
1276 r[0] = x;
1277 r[1] = 0;
1278 r[2] = 0;
1279 r[3] = 0;
1280 r[4] = 0;
1281 r[5] = y;
1282 r[6] = 0;
1283 r[7] = 0;
1284 r[8] = 0;
1285 r[9] = 0;
1286 r[10] = z;
1287 r[11] = 0;
1288 r[12] = 0;
1289 r[13] = 0;
1290 r[14] = 0;
1291 r[15] = 1;
1293 return r;
1294 };
1296 /*
1297 * Function: M4x4.makeScale1
1299 * Creates a transformation matrix for a uniform scale by a single scalar value.
1301 * Parameters:
1303 * k - the scale factor
1304 * r - optional 4x4 matrix to store the result in
1306 * Returns:
1308 * If r is specified, returns r after creating the matrix.
1309 * Otherwise, returns a new 4x4 matrix with the result.
1310 */
1311 M4x4.makeScale1 = function M4x4_makeScale1(k, r) {
1312 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1314 return M4x4.makeScale3(k, k, k, r);
1315 };
1317 /*
1318 * Function: M4x4.makeScale
1320 * Creates a transformation matrix for scaling each of the x, y, and z axes by the amount
1321 * given in the corresponding element of the 3-element vector.
1323 * Parameters:
1325 * v - the 3-element vector containing the scale factors
1326 * r - optional 4x4 matrix to store the result in
1328 * Returns:
1330 * If r is specified, returns r after creating the matrix.
1331 * Otherwise, returns a new 4x4 matrix with the result.
1332 */
1333 M4x4.makeScale = function M4x4_makeScale(v, r) {
1334 //MathUtils_assert(v.length == 3, "v.length == 3");
1335 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1337 return M4x4.makeScale3(v[0], v[1], v[2], r);
1338 };
1340 /*
1341 * Function: M4x4.scale3
1342 */
1343 M4x4.scale3 = function M4x4_scale3(x, y, z, m, r) {
1344 //MathUtils_assert(m.length == 16, "m.length == 16");
1345 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1347 if (r == m) {
1348 m[0] *= x;
1349 m[1] *= x;
1350 m[2] *= x;
1351 m[3] *= x;
1352 m[4] *= y;
1353 m[5] *= y;
1354 m[6] *= y;
1355 m[7] *= y;
1356 m[8] *= z;
1357 m[9] *= z;
1358 m[10] *= z;
1359 m[11] *= z;
1360 return m;
1363 if (r == undefined)
1364 r = new MJS_FLOAT_ARRAY_TYPE(16);
1366 r[0] = m[0] * x;
1367 r[1] = m[1] * x;
1368 r[2] = m[2] * x;
1369 r[3] = m[3] * x;
1370 r[4] = m[4] * y;
1371 r[5] = m[5] * y;
1372 r[6] = m[6] * y;
1373 r[7] = m[7] * y;
1374 r[8] = m[8] * z;
1375 r[9] = m[9] * z;
1376 r[10] = m[10] * z;
1377 r[11] = m[11] * z;
1378 r[12] = m[12];
1379 r[13] = m[13];
1380 r[14] = m[14];
1381 r[15] = m[15];
1383 return r;
1384 };
1386 /*
1387 * Function: M4x4.scale1
1388 */
1389 M4x4.scale1 = function M4x4_scale1(k, m, r) {
1390 //MathUtils_assert(m.length == 16, "m.length == 16");
1391 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1392 if (r == m) {
1393 m[0] *= k;
1394 m[1] *= k;
1395 m[2] *= k;
1396 m[3] *= k;
1397 m[4] *= k;
1398 m[5] *= k;
1399 m[6] *= k;
1400 m[7] *= k;
1401 m[8] *= k;
1402 m[9] *= k;
1403 m[10] *= k;
1404 m[11] *= k;
1405 return m;
1409 if (r == undefined)
1410 r = new MJS_FLOAT_ARRAY_TYPE(16);
1412 r[0] = m[0] * k;
1413 r[1] = m[1] * k;
1414 r[2] = m[2] * k;
1415 r[3] = m[3] * k;
1416 r[4] = m[4] * k;
1417 r[5] = m[5] * k;
1418 r[6] = m[6] * k;
1419 r[7] = m[7] * k;
1420 r[8] = m[8] * k;
1421 r[9] = m[9] * k;
1422 r[10] = m[10] * k;
1423 r[11] = m[11] * k;
1424 r[12] = m[12];
1425 r[13] = m[13];
1426 r[14] = m[14];
1427 r[15] = m[15];
1429 return r;
1430 };
1432 /*
1433 * Function: M4x4.scale1
1434 */
1435 M4x4.scale = function M4x4_scale(v, m, r) {
1436 //MathUtils_assert(v.length == 3, "v.length == 3");
1437 //MathUtils_assert(m.length == 16, "m.length == 16");
1438 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1439 var x = v[0], y = v[1], z = v[2];
1441 if (r == m) {
1442 m[0] *= x;
1443 m[1] *= x;
1444 m[2] *= x;
1445 m[3] *= x;
1446 m[4] *= y;
1447 m[5] *= y;
1448 m[6] *= y;
1449 m[7] *= y;
1450 m[8] *= z;
1451 m[9] *= z;
1452 m[10] *= z;
1453 m[11] *= z;
1454 return m;
1457 if (r == undefined)
1458 r = new MJS_FLOAT_ARRAY_TYPE(16);
1461 r[0] = m[0] * x;
1462 r[1] = m[1] * x;
1463 r[2] = m[2] * x;
1464 r[3] = m[3] * x;
1465 r[4] = m[4] * y;
1466 r[5] = m[5] * y;
1467 r[6] = m[6] * y;
1468 r[7] = m[7] * y;
1469 r[8] = m[8] * z;
1470 r[9] = m[9] * z;
1471 r[10] = m[10] * z;
1472 r[11] = m[11] * z;
1473 r[12] = m[12];
1474 r[13] = m[13];
1475 r[14] = m[14];
1476 r[15] = m[15];
1478 return r;
1479 };
1481 /*
1482 * Function: M4x4.makeTranslate3
1483 */
1484 M4x4.makeTranslate3 = function M4x4_makeTranslate3(x, y, z, r) {
1485 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1487 if (r == undefined)
1488 r = new MJS_FLOAT_ARRAY_TYPE(16);
1490 r[0] = 1;
1491 r[1] = 0;
1492 r[2] = 0;
1493 r[3] = 0;
1494 r[4] = 0;
1495 r[5] = 1;
1496 r[6] = 0;
1497 r[7] = 0;
1498 r[8] = 0;
1499 r[9] = 0;
1500 r[10] = 1;
1501 r[11] = 0;
1502 r[12] = x;
1503 r[13] = y;
1504 r[14] = z;
1505 r[15] = 1;
1507 return r;
1508 };
1510 /*
1511 * Function: M4x4.makeTranslate1
1512 */
1513 M4x4.makeTranslate1 = function M4x4_makeTranslate1 (k, r) {
1514 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1516 return M4x4.makeTranslate3(k, k, k, r);
1517 };
1519 /*
1520 * Function: M4x4.makeTranslate
1521 */
1522 M4x4.makeTranslate = function M4x4_makeTranslate (v, r) {
1523 //MathUtils_assert(v.length == 3, "v.length == 3");
1524 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1526 return M4x4.makeTranslate3(v[0], v[1], v[2], r);
1527 };
1529 /*
1530 * Function: M4x4.translate3Self
1531 */
1532 M4x4.translate3Self = function M4x4_translate3Self (x, y, z, m) {
1533 //MathUtils_assert(m.length == 16, "m.length == 16");
1534 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1535 m[12] += m[0] * x + m[4] * y + m[8] * z;
1536 m[13] += m[1] * x + m[5] * y + m[9] * z;
1537 m[14] += m[2] * x + m[6] * y + m[10] * z;
1538 m[15] += m[3] * x + m[7] * y + m[11] * z;
1539 return m;
1540 };
1542 /*
1543 * Function: M4x4.translate3
1544 */
1545 M4x4.translate3 = function M4x4_translate3 (x, y, z, m, r) {
1546 //MathUtils_assert(m.length == 16, "m.length == 16");
1547 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1549 if (r == m) {
1550 m[12] += m[0] * x + m[4] * y + m[8] * z;
1551 m[13] += m[1] * x + m[5] * y + m[9] * z;
1552 m[14] += m[2] * x + m[6] * y + m[10] * z;
1553 m[15] += m[3] * x + m[7] * y + m[11] * z;
1554 return m;
1557 if (r == undefined)
1558 r = new MJS_FLOAT_ARRAY_TYPE(16);
1560 var m11 = m[0];
1561 var m21 = m[1];
1562 var m31 = m[2];
1563 var m41 = m[3];
1564 var m12 = m[4];
1565 var m22 = m[5];
1566 var m32 = m[6];
1567 var m42 = m[7];
1568 var m13 = m[8];
1569 var m23 = m[9];
1570 var m33 = m[10];
1571 var m43 = m[11];
1574 r[0] = m11;
1575 r[1] = m21;
1576 r[2] = m31;
1577 r[3] = m41;
1578 r[4] = m12;
1579 r[5] = m22;
1580 r[6] = m32;
1581 r[7] = m42;
1582 r[8] = m13;
1583 r[9] = m23;
1584 r[10] = m33;
1585 r[11] = m43;
1586 r[12] = m11 * x + m12 * y + m13 * z + m[12];
1587 r[13] = m21 * x + m22 * y + m23 * z + m[13];
1588 r[14] = m31 * x + m32 * y + m33 * z + m[14];
1589 r[15] = m41 * x + m42 * y + m43 * z + m[15];
1591 return r;
1592 };
1594 /*
1595 * Function: M4x4.translate1
1596 */
1597 M4x4.translate1 = function M4x4_translate1 (k, m, r) {
1598 //MathUtils_assert(m.length == 16, "m.length == 16");
1599 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1601 return M4x4.translate3(k, k, k, m, r);
1602 };
1603 /*
1604 * Function: M4x4.translateSelf
1605 */
1606 M4x4.translateSelf = function M4x4_translateSelf (v, m) {
1607 //MathUtils_assert(v.length == 3, "v.length == 3");
1608 //MathUtils_assert(m.length == 16, "m.length == 16");
1609 var x=v[0], y=v[1], z=v[2];
1610 m[12] += m[0] * x + m[4] * y + m[8] * z;
1611 m[13] += m[1] * x + m[5] * y + m[9] * z;
1612 m[14] += m[2] * x + m[6] * y + m[10] * z;
1613 m[15] += m[3] * x + m[7] * y + m[11] * z;
1614 return m;
1615 };
1616 /*
1617 * Function: M4x4.translate
1618 */
1619 M4x4.translate = function M4x4_translate (v, m, r) {
1620 //MathUtils_assert(v.length == 3, "v.length == 3");
1621 //MathUtils_assert(m.length == 16, "m.length == 16");
1622 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1623 var x=v[0], y=v[1], z=v[2];
1624 if (r == m) {
1625 m[12] += m[0] * x + m[4] * y + m[8] * z;
1626 m[13] += m[1] * x + m[5] * y + m[9] * z;
1627 m[14] += m[2] * x + m[6] * y + m[10] * z;
1628 m[15] += m[3] * x + m[7] * y + m[11] * z;
1629 return m;
1632 if (r == undefined)
1633 r = new MJS_FLOAT_ARRAY_TYPE(16);
1635 var m11 = m[0];
1636 var m21 = m[1];
1637 var m31 = m[2];
1638 var m41 = m[3];
1639 var m12 = m[4];
1640 var m22 = m[5];
1641 var m32 = m[6];
1642 var m42 = m[7];
1643 var m13 = m[8];
1644 var m23 = m[9];
1645 var m33 = m[10];
1646 var m43 = m[11];
1648 r[0] = m11;
1649 r[1] = m21;
1650 r[2] = m31;
1651 r[3] = m41;
1652 r[4] = m12;
1653 r[5] = m22;
1654 r[6] = m32;
1655 r[7] = m42;
1656 r[8] = m13;
1657 r[9] = m23;
1658 r[10] = m33;
1659 r[11] = m43;
1660 r[12] = m11 * x + m12 * y + m13 * z + m[12];
1661 r[13] = m21 * x + m22 * y + m23 * z + m[13];
1662 r[14] = m31 * x + m32 * y + m33 * z + m[14];
1663 r[15] = m41 * x + m42 * y + m43 * z + m[15];
1665 return r;
1666 };
1668 /*
1669 * Function: M4x4.makeLookAt
1670 */
1671 M4x4.makeLookAt = function M4x4_makeLookAt (eye, center, up, r) {
1672 //MathUtils_assert(eye.length == 3, "eye.length == 3");
1673 //MathUtils_assert(center.length == 3, "center.length == 3");
1674 //MathUtils_assert(up.length == 3, "up.length == 3");
1675 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1677 var z = V3.direction(eye, center, V3._temp1);
1678 var x = V3.normalize(V3.cross(up, z, V3._temp2), V3._temp2);
1679 var y = V3.normalize(V3.cross(z, x, V3._temp3), V3._temp3);
1681 var tm1 = M4x4._temp1;
1682 var tm2 = M4x4._temp2;
1684 tm1[0] = x[0];
1685 tm1[1] = y[0];
1686 tm1[2] = z[0];
1687 tm1[3] = 0;
1688 tm1[4] = x[1];
1689 tm1[5] = y[1];
1690 tm1[6] = z[1];
1691 tm1[7] = 0;
1692 tm1[8] = x[2];
1693 tm1[9] = y[2];
1694 tm1[10] = z[2];
1695 tm1[11] = 0;
1696 tm1[12] = 0;
1697 tm1[13] = 0;
1698 tm1[14] = 0;
1699 tm1[15] = 1;
1701 tm2[0] = 1; tm2[1] = 0; tm2[2] = 0; tm2[3] = 0;
1702 tm2[4] = 0; tm2[5] = 1; tm2[6] = 0; tm2[7] = 0;
1703 tm2[8] = 0; tm2[9] = 0; tm2[10] = 1; tm2[11] = 0;
1704 tm2[12] = -eye[0]; tm2[13] = -eye[1]; tm2[14] = -eye[2]; tm2[15] = 1;
1706 if (r == undefined)
1707 r = new MJS_FLOAT_ARRAY_TYPE(16);
1708 return M4x4.mul(tm1, tm2, r);
1709 };
1711 /*
1712 * Function: M4x4.transposeSelf
1713 */
1714 M4x4.transposeSelf = function M4x4_transposeSelf (m) {
1715 //MathUtils_assert(m.length == 16, "m.length == 16");
1716 var tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1717 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1718 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1719 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1720 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1721 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1722 return m;
1723 };
1724 /*
1725 * Function: M4x4.transpose
1726 */
1727 M4x4.transpose = function M4x4_transpose (m, r) {
1728 //MathUtils_assert(m.length == 16, "m.length == 16");
1729 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1731 if (m == r) {
1732 var tmp = 0.0;
1733 tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1734 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1735 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1736 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1737 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1738 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1739 return m;
1742 if (r == undefined)
1743 r = new MJS_FLOAT_ARRAY_TYPE(16);
1745 r[0] = m[0]; r[1] = m[4]; r[2] = m[8]; r[3] = m[12];
1746 r[4] = m[1]; r[5] = m[5]; r[6] = m[9]; r[7] = m[13];
1747 r[8] = m[2]; r[9] = m[6]; r[10] = m[10]; r[11] = m[14];
1748 r[12] = m[3]; r[13] = m[7]; r[14] = m[11]; r[15] = m[15];
1750 return r;
1751 };
1754 /*
1755 * Function: M4x4.transformPoint
1756 */
1757 M4x4.transformPoint = function M4x4_transformPoint (m, v, r) {
1758 //MathUtils_assert(m.length == 16, "m.length == 16");
1759 //MathUtils_assert(v.length == 3, "v.length == 3");
1760 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1761 if (r == undefined)
1762 r = new MJS_FLOAT_ARRAY_TYPE(3);
1764 var v0 = v[0], v1 = v[1], v2 = v[2];
1766 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1767 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1768 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1769 var w = m[3] * v0 + m[7] * v1 + m[11] * v2 + m[15];
1771 if (w != 1.0) {
1772 r[0] /= w;
1773 r[1] /= w;
1774 r[2] /= w;
1777 return r;
1778 };
1780 /*
1781 * Function: M4x4.transformLine
1782 */
1783 M4x4.transformLine = function M4x4_transformLine(m, v, r) {
1784 //MathUtils_assert(m.length == 16, "m.length == 16");
1785 //MathUtils_assert(v.length == 3, "v.length == 3");
1786 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1787 if (r == undefined)
1788 r = new MJS_FLOAT_ARRAY_TYPE(3);
1790 var v0 = v[0], v1 = v[1], v2 = v[2];
1791 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1792 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1793 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1794 var w = m[3] * v0 + m[7] * v1 + m[11] * v2;
1796 if (w != 1.0) {
1797 r[0] /= w;
1798 r[1] /= w;
1799 r[2] /= w;
1802 return r;
1803 };
1806 /*
1807 * Function: M4x4.transformPointAffine
1808 */
1809 M4x4.transformPointAffine = function M4x4_transformPointAffine (m, v, r) {
1810 //MathUtils_assert(m.length == 16, "m.length == 16");
1811 //MathUtils_assert(v.length == 3, "v.length == 3");
1812 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1813 if (r == undefined)
1814 r = new MJS_FLOAT_ARRAY_TYPE(3);
1816 var v0 = v[0], v1 = v[1], v2 = v[2];
1818 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1819 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1820 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1822 return r;
1823 };
1825 /*
1826 * Function: M4x4.transformLineAffine
1827 */
1828 M4x4.transformLineAffine = function M4x4_transformLineAffine(m, v, r) {
1829 //MathUtils_assert(m.length == 16, "m.length == 16");
1830 //MathUtils_assert(v.length == 3, "v.length == 3");
1831 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1832 if (r == undefined)
1833 r = new MJS_FLOAT_ARRAY_TYPE(3);
1835 var v0 = v[0], v1 = v[1], v2 = v[2];
1836 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1837 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1838 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1840 return r;
1841 };
1843 M4x4.makeCoords = function M4x4_makeCoords(vx,vy,vz) {
1845 var r = new MJS_FLOAT_ARRAY_TYPE(16);
1847 r[0] = vx[0];
1848 r[1] = vx[1];
1849 r[2] = vx[2];
1850 r[3] = 0;
1851 r[4] = vy[0];
1852 r[5] = vy[1];
1853 r[6] = vy[2];
1854 r[7] = 0;
1855 r[8] = vz[0];
1856 r[9] = vz[1];
1857 r[10] = vz[2];
1858 r[11] = 0;
1859 r[12] = 0;
1860 r[13] = 0;
1861 r[14] = 0;
1862 r[15] = 1;
1864 return r;
1866 };
1868 return {
1869 V3: V3,
1870 v3: F3(V3.$),
1871 v3clone: V3.clone,
1872 v3add: F2(V3.add),
1873 v3sub: F2(V3.sub),
1874 v3neg: V3.neg,
1875 v3direction: F2(V3.direction),
1876 v3length: V3.length,
1877 v3lengthSquared: V3.lengthSquared,
1878 v3normalize: V3.normalize,
1879 v3scale: F2(V3.scale),
1880 v3dot: F2(V3.dot),
1881 v3cross: F2(V3.cross),
1882 v3mul4x4: F2(V3.mul4x4),
1883 /*
1884 m4x4: F16(M4x4.$),
1885 */
1886 M4x4:M4x4,
1887 m4x4identity: M4x4.identity,
1888 m4x4clone: M4x4.clone,
1889 m4x4topLeft3x3: M4x4.topLeft3x3,
1890 m4x4inverseOrthonormal: M4x4.inverseOrthonormal,
1891 m4x4inverseTo3x3: M4x4.inverseTo3x3,
1892 m4x4makeFrustum: F6(M4x4.makeFrustum),
1893 m4x4makePerspective: F4(M4x4.makePerspective),
1894 m4x4makeOrtho: F6(M4x4.makeOrtho),
1895 m4x4makeOrtho2D: F4(M4x4.makeOrtho2D),
1896 m4x4mul: F2(M4x4.mul),
1897 m4x4Affine: F2(M4x4.mulAffine),
1898 m4x4makeRotate: F2(M4x4.makeRotate),
1899 m4x4rotate: F3(M4x4.rotate),
1900 m4x4makeScale3: F3(M4x4.makeScale3),
1901 m4x4makeScale1: M4x4.makeScale1,
1902 m4x4makeScale: M4x4.makeScale,
1903 m4x4scale3: F4(M4x4.scale3),
1904 m4x4scale1: F2(M4x4.scale1),
1905 m4x4scale: F2(M4x4.scale),
1906 m4x4makeTranslate3: F3(M4x4.makeTranslate3),
1907 m4x4makeTranslate1: M4x4.makeTranslate1,
1908 m4x4makeTranslate: M4x4.makeTranslate,
1909 m4x4translate3: F4(M4x4.translate3),
1910 m4x4translate1: F2(M4x4.translate1),
1911 m4x4translate: F2(M4x4.translate),
1912 m4x4makeLookAt: F3(M4x4.makeLookAt),
1913 m4x4transpose: M4x4.transpose,
1914 m4x4transformPoint: F2(M4x4.transformPoint),
1915 /*
1916 m4x4_transformLine(m, v, r) {
1917 m4x4_transformPointFffine (m, v, r) {
1918 m4x4_transformLineFffine(m, v, r) {
1919 */
1920 m4x4makeCoords: F3(M4x4.makeCoords),
1921 };