on d99e412 help sign in
1783 lines 53 kB history raw
2/*
3 * Copyright (c) 2010 Mozilla Corporation
4 * Copyright (c) 2010 Vladimir Vukicevic
5 * Copyright (c) 2013 John Mayer
6 *
7 * Permission is hereby granted, free of charge, to any person
8 * obtaining a copy of this software and associated documentation
9 * files (the "Software"), to deal in the Software without
10 * restriction, including without limitation the rights to use,
11 * copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following
14 * conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
27 */
29/*
30 * File: mjs
31 *
32 * Vector and Matrix math utilities for JavaScript, optimized for WebGL.
33 * Edited to work with 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 = 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 //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 //} 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 /* Function: V3.toTuple3
159 *
160 * Turn into an Elm Tuple
161 */
162 V3.toTuple3 = function V3_toTuple3(a) {
163 return v = {
164 ctor:"_Tuple3",
165 _0:a[0],
166 _1:a[1],
167 _2:a[2]
168 };
169 };
171 /*
172 * Function: V3.add
173 *
174 * Perform r = a + b.
175 *
176 * Parameters:
177 *
178 * a - the first vector operand
179 * b - the second vector operand
180 * r - optional vector to store the result in
181 *
182 * Returns:
183 *
184 * If r is specified, returns r after performing the operation.
185 * Otherwise, returns a new 3-element vector with the result.
186 */
187 V3.add = function V3_add(a, b, r) {
188 //MathUtils_assert(a.length == 3, "a.length == 3");
189 //MathUtils_assert(b.length == 3, "b.length == 3");
190 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
192 if (r == undefined)
193 r = new MJS_FLOAT_ARRAY_TYPE(3);
194 r[0] = a[0] + b[0];
195 r[1] = a[1] + b[1];
196 r[2] = a[2] + b[2];
197 return r;
198 };
200 /*
201 * Function: V3.sub
202 *
203 * Perform
204 * r = a - b.
205 *
206 * Parameters:
207 *
208 * a - the first vector operand
209 * b - the second vector operand
210 * r - optional vector to store the result in
211 *
212 * Returns:
213 *
214 * If r is specified, returns r after performing the operation.
215 * Otherwise, returns a new 3-element vector with the result.
216 */
217 V3.sub = function V3_sub(a, b, r) {
218 //MathUtils_assert(a.length == 3, "a.length == 3");
219 //MathUtils_assert(b.length == 3, "b.length == 3");
220 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
222 if (r == undefined)
223 r = new MJS_FLOAT_ARRAY_TYPE(3);
224 r[0] = a[0] - b[0];
225 r[1] = a[1] - b[1];
226 r[2] = a[2] - b[2];
227 return r;
228 };
230 /*
231 * Function: V3.neg
232 *
233 * Perform
234 * r = - a.
235 *
236 * Parameters:
237 *
238 * a - the vector operand
239 * r - optional vector to store the result in
240 *
241 * Returns:
242 *
243 * If r is specified, returns r after performing the operation.
244 * Otherwise, returns a new 3-element vector with the result.
245 */
246 V3.neg = function V3_neg(a, r) {
247 //MathUtils_assert(a.length == 3, "a.length == 3");
248 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
250 if (r == undefined)
251 r = new MJS_FLOAT_ARRAY_TYPE(3);
252 r[0] = - a[0];
253 r[1] = - a[1];
254 r[2] = - a[2];
255 return r;
256 };
258 /*
259 * Function: V3.direction
260 *
261 * Perform
262 * r = (a - b) / |a - b|. The result is the normalized
263 * direction from a to b.
264 *
265 * Parameters:
266 *
267 * a - the first vector operand
268 * b - the second vector operand
269 * r - optional vector to store the result in
270 *
271 * Returns:
272 *
273 * If r is specified, returns r after performing the operation.
274 * Otherwise, returns a new 3-element vector with the result.
275 */
276 V3.direction = function V3_direction(a, b, r) {
277 //MathUtils_assert(a.length == 3, "a.length == 3");
278 //MathUtils_assert(b.length == 3, "b.length == 3");
279 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
281 if (r == undefined)
282 r = new MJS_FLOAT_ARRAY_TYPE(3);
283 return V3.normalize(V3.sub(a, b, r), r);
284 };
286 /*
287 * Function: V3.length
288 *
289 * Perform r = |a|.
290 *
291 * Parameters:
292 *
293 * a - the vector operand
294 *
295 * Returns:
296 *
297 * The length of the given vector.
298 */
299 V3.length = function V3_length(a) {
300 //MathUtils_assert(a.length == 3, "a.length == 3");
302 return Math.sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
303 };
305 /*
306 * Function: V3.lengthSquard
307 *
308 * Perform r = |a|*|a|.
309 *
310 * Parameters:
311 *
312 * a - the vector operand
313 *
314 * Returns:
315 *
316 * The square of the length of the given vector.
317 */
318 V3.lengthSquared = function V3_lengthSquared(a) {
319 //MathUtils_assert(a.length == 3, "a.length == 3");
321 return a[0]*a[0] + a[1]*a[1] + a[2]*a[2];
322 };
324 /*
325 * Function: V3.normalize
326 *
327 * Perform r = a / |a|.
328 *
329 * Parameters:
330 *
331 * a - the vector operand
332 * r - optional vector to store the result in
333 *
334 * Returns:
335 *
336 * If r is specified, returns r after performing the operation.
337 * Otherwise, returns a new 3-element vector with the result.
338 */
339 V3.normalize = function V3_normalize(a, r) {
340 //MathUtils_assert(a.length == 3, "a.length == 3");
341 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
343 if (r == undefined)
344 r = new MJS_FLOAT_ARRAY_TYPE(3);
345 var im = 1.0 / V3.length(a);
346 r[0] = a[0] * im;
347 r[1] = a[1] * im;
348 r[2] = a[2] * im;
349 return r;
350 };
352 /*
353 * Function: V3.scale
354 *
355 * Perform r = a * k.
356 *
357 * Parameters:
358 *
359 * a - the vector operand
360 * k - a scalar value
361 * r - optional vector to store the result in
362 *
363 * Returns:
364 *
365 * If r is specified, returns r after performing the operation.
366 * Otherwise, returns a new 3-element vector with the result.
367 */
368 V3.scale = function V3_scale(a, k, r) {
369 //MathUtils_assert(a.length == 3, "a.length == 3");
370 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
372 if (r == undefined)
373 r = new MJS_FLOAT_ARRAY_TYPE(3);
374 r[0] = a[0] * k;
375 r[1] = a[1] * k;
376 r[2] = a[2] * k;
377 return r;
378 };
380 /*
381 * Function: V3.dot
382 *
383 * Perform
384 * r = dot(a, b).
385 *
386 * Parameters:
387 *
388 * a - the first vector operand
389 * b - the second vector operand
390 *
391 * Returns:
392 *
393 * The dot product of a and b.
394 */
395 V3.dot = function V3_dot(a, b) {
396 //MathUtils_assert(a.length == 3, "a.length == 3");
397 //MathUtils_assert(b.length == 3, "b.length == 3");
399 return a[0] * b[0] +
400 a[1] * b[1] +
401 a[2] * b[2];
402 };
404 /*
405 * Function: V3.cross
406 *
407 * Perform r = a x b.
408 *
409 * Parameters:
410 *
411 * a - the first vector operand
412 * b - the second vector operand
413 * r - optional vector to store the result in
414 *
415 * Returns:
416 *
417 * If r is specified, returns r after performing the operation.
418 * Otherwise, returns a new 3-element vector with the result.
419 */
420 V3.cross = function V3_cross(a, b, r) {
421 //MathUtils_assert(a.length == 3, "a.length == 3");
422 //MathUtils_assert(b.length == 3, "b.length == 3");
423 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
425 if (r == undefined)
426 r = new MJS_FLOAT_ARRAY_TYPE(3);
427 r[0] = a[1]*b[2] - a[2]*b[1];
428 r[1] = a[2]*b[0] - a[0]*b[2];
429 r[2] = a[0]*b[1] - a[1]*b[0];
430 return r;
431 };
433 /*
434 * Function: V3.mul4x4
435 *
436 * Perform
437 * r = m * v.
438 *
439 * Parameters:
440 *
441 * m - the 4x4 matrix operand
442 * v - the 3-element vector operand
443 * r - optional vector to store the result in
444 *
445 * Returns:
446 *
447 * If r is specified, returns r after performing the operation.
448 * Otherwise, returns a new 3-element vector with the result.
449 * The 4-element result vector is divided by the w component
450 * and returned as a 3-element vector.
451 */
452 V3.mul4x4 = function V3_mul4x4(m, v, r) {
453 //MathUtils_assert(m.length == 16, "m.length == 16");
454 //MathUtils_assert(v.length == 3, "v.length == 3");
455 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
457 var w;
458 var tmp = V3._temp1;
459 if (r == undefined)
460 r = new MJS_FLOAT_ARRAY_TYPE(3);
461 tmp[0] = m[ 3];
462 tmp[1] = m[ 7];
463 tmp[2] = m[11];
464 w = V3.dot(v, tmp) + m[15];
465 tmp[0] = m[ 0];
466 tmp[1] = m[ 4];
467 tmp[2] = m[ 8];
468 r[0] = (V3.dot(v, tmp) + m[12])/w;
469 tmp[0] = m[ 1];
470 tmp[1] = m[ 5];
471 tmp[2] = m[ 9];
472 r[1] = (V3.dot(v, tmp) + m[13])/w;
473 tmp[0] = m[ 2];
474 tmp[1] = m[ 6];
475 tmp[2] = m[10];
476 r[2] = (V3.dot(v, tmp) + m[14])/w;
477 return r;
478 };
480 /*
481 * Class: M4x4
482 *
483 * Methods for working with 4x4 matrices. A matrix is represented by a 16-element array
484 * in column-major order. Any valid JavaScript array type may be used, but if new
485 * matrices are created they are created using the configured MJS_FLOAT_ARRAY_TYPE.
486 */
488 var M4x4 = { };
490 M4x4._temp1 = new MJS_FLOAT_ARRAY_TYPE(16);
491 M4x4._temp2 = new MJS_FLOAT_ARRAY_TYPE(16);
493 if (MJS_FLOAT_ARRAY_TYPE == Array) {
494 M4x4.I = [1.0, 0.0, 0.0, 0.0,
495 0.0, 1.0, 0.0, 0.0,
496 0.0, 0.0, 1.0, 0.0,
497 0.0, 0.0, 0.0, 1.0];
499 M4x4.$ = function M4x4_$(m00, m01, m02, m03,
500 m04, m05, m06, m07,
501 m08, m09, m10, m11,
502 m12, m13, m14, m15)
503 {
504 return [m00, m01, m02, m03,
505 m04, m05, m06, m07,
506 m08, m09, m10, m11,
507 m12, m13, m14, m15];
508 };
510 M4x4.clone = function M4x4_clone(m) {
511 //MathUtils_assert(m.length == 16, "m.length == 16");
512 return new [m[0], m[1], m[2], m[3],
513 m[4], m[5], m[6], m[7],
514 m[8], m[9], m[10], m[11],
515 m[12], m[13], m[14], m[15]];
516 };
517 } else {
518 M4x4.I = new MJS_FLOAT_ARRAY_TYPE([1.0, 0.0, 0.0, 0.0,
519 0.0, 1.0, 0.0, 0.0,
520 0.0, 0.0, 1.0, 0.0,
521 0.0, 0.0, 0.0, 1.0]);
523 /*
524 * Function: M4x4.$
525 *
526 * Creates a new 4x4 matrix with the given values.
527 *
528 * Parameters:
529 *
530 * m00..m15 - the 16 elements of the new matrix.
531 *
532 * Returns:
533 *
534 * A new matrix filled with the given argument values.
535 */
536 M4x4.$ = function M4x4_$(m00, m01, m02, m03,
537 m04, m05, m06, m07,
538 m08, m09, m10, m11,
539 m12, m13, m14, m15)
540 {
541 return new MJS_FLOAT_ARRAY_TYPE([m00, m01, m02, m03,
542 m04, m05, m06, m07,
543 m08, m09, m10, m11,
544 m12, m13, m14, m15]);
545 };
547 /*
548 * Function: M4x4.clone
549 *
550 * Clone the given 4x4 matrix.
551 *
552 * Parameters:
553 *
554 * m - the 4x4 matrix to clone
555 *
556 * Returns:
557 *
558 * A new matrix with the same values as the passed-in one.
559 */
560 M4x4.clone = function M4x4_clone(m) {
561 //MathUtils_assert(m.length == 16, "m.length == 16");
562 return new MJS_FLOAT_ARRAY_TYPE(m);
563 };
564 }
566 M4x4.identity = M4x4.I;
568 /*
569 * Function: M4x4.topLeft3x3
570 *
571 * Return the top left 3x3 matrix from the given 4x4 matrix m.
572 *
573 * Parameters:
574 *
575 * m - the matrix
576 * r - optional 3x3 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 3x3 matrix with the result.
582 */
583 M4x4.topLeft3x3 = function M4x4_topLeft3x3(m, r) {
584 //MathUtils_assert(m.length == 16, "m.length == 16");
585 //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
587 if (r == undefined)
588 r = new MJS_FLOAT_ARRAY_TYPE(9);
589 r[0] = m[0]; r[1] = m[1]; r[2] = m[2];
590 r[3] = m[4]; r[4] = m[5]; r[5] = m[6];
591 r[6] = m[8]; r[7] = m[9]; r[8] = m[10];
592 return r;
593 };
595 /*
596 * Function: M4x4.inverseOrthonormal
597 *
598 * Computes the inverse of the given matrix m, assuming that
599 * the matrix is orthonormal.
600 *
601 * Parameters:
602 *
603 * m - the matrix
604 * r - optional 4x4 matrix to store the result in
605 *
606 * Returns:
607 *
608 * If r is specified, returns r after performing the operation.
609 * Otherwise, returns a new 4x4 matrix with the result.
610 */
611 M4x4.inverseOrthonormal = function M4x4_inverseOrthonormal(m, r) {
612 //MathUtils_assert(m.length == 16, "m.length == 16");
613 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
614 //MathUtils_assert(m != r, "m != r");
616 if (r == undefined)
617 r = new MJS_FLOAT_ARRAY_TYPE(16);
618 M4x4.transpose(m, r);
619 var t = [m[12], m[13], m[14]];
620 r[3] = r[7] = r[11] = 0;
621 r[12] = -V3.dot([r[0], r[4], r[8]], t);
622 r[13] = -V3.dot([r[1], r[5], r[9]], t);
623 r[14] = -V3.dot([r[2], r[6], r[10]], t);
624 return r;
625 };
627 /*
628 * Function: M4x4.inverseTo3x3
629 *
630 * Computes the inverse of the given matrix m, but calculates
631 * only the top left 3x3 values of the result.
632 *
633 * Parameters:
634 *
635 * m - the matrix
636 * r - optional 3x3 matrix to store the result in
637 *
638 * Returns:
639 *
640 * If r is specified, returns r after performing the operation.
641 * Otherwise, returns a new 3x3 matrix with the result.
642 */
643 M4x4.inverseTo3x3 = function M4x4_inverseTo3x3(m, r) {
644 //MathUtils_assert(m.length == 16, "m.length == 16");
645 //MathUtils_assert(r == undefined || r.length == 9, "r == undefined || r.length == 9");
647 if (r == undefined)
648 r = new MJS_FLOAT_ARRAY_TYPE(9);
650 var a11 = m[10]*m[5]-m[6]*m[9],
651 a21 = -m[10]*m[1]+m[2]*m[9],
652 a31 = m[6]*m[1]-m[2]*m[5],
653 a12 = -m[10]*m[4]+m[6]*m[8],
654 a22 = m[10]*m[0]-m[2]*m[8],
655 a32 = -m[6]*m[0]+m[2]*m[4],
656 a13 = m[9]*m[4]-m[5]*m[8],
657 a23 = -m[9]*m[0]+m[1]*m[8],
658 a33 = m[5]*m[0]-m[1]*m[4];
659 var det = m[0]*(a11) + m[1]*(a12) + m[2]*(a13);
660 if (det == 0) // no inverse
661 throw "matrix not invertible";
662 var idet = 1.0 / det;
664 r[0] = idet*a11;
665 r[1] = idet*a21;
666 r[2] = idet*a31;
667 r[3] = idet*a12;
668 r[4] = idet*a22;
669 r[5] = idet*a32;
670 r[6] = idet*a13;
671 r[7] = idet*a23;
672 r[8] = idet*a33;
674 return r;
675 };
677 /*
678 * Function: M4x4.makeFrustum
679 *
680 * Creates a matrix for a projection frustum with the given parameters.
681 *
682 * Parameters:
683 *
684 * left - the left coordinate of the frustum
685 * right- the right coordinate of the frustum
686 * bottom - the bottom coordinate of the frustum
687 * top - the top coordinate of the frustum
688 * znear - the near z distance of the frustum
689 * zfar - the far z distance of the frustum
690 * r - optional 4x4 matrix to store the result in
691 *
692 * Returns:
693 *
694 * If r is specified, returns r after creating the projection matrix.
695 * Otherwise, returns a new 4x4 matrix.
696 */
697 M4x4.makeFrustum = function M4x4_makeFrustum(left, right, bottom, top, znear, zfar, r) {
698 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
700 if (r == undefined)
701 r = new MJS_FLOAT_ARRAY_TYPE(16);
703 var X = 2*znear/(right-left);
704 var Y = 2*znear/(top-bottom);
705 var A = (right+left)/(right-left);
706 var B = (top+bottom)/(top-bottom);
707 var C = -(zfar+znear)/(zfar-znear);
708 var D = -2*zfar*znear/(zfar-znear);
710 r[0] = 2*znear/(right-left);
711 r[1] = 0;
712 r[2] = 0;
713 r[3] = 0;
714 r[4] = 0;
715 r[5] = 2*znear/(top-bottom);
716 r[6] = 0;
717 r[7] = 0;
718 r[8] = (right+left)/(right-left);
719 r[9] = (top+bottom)/(top-bottom);
720 r[10] = -(zfar+znear)/(zfar-znear);
721 r[11] = -1;
722 r[12] = 0;
723 r[13] = 0;
724 r[14] = -2*zfar*znear/(zfar-znear);
725 r[15] = 0;
727 return r;
728 };
730 /*
731 * Function: M4x4.makePerspective
732 *
733 * Creates a matrix for a perspective projection with the given parameters.
734 *
735 * Parameters:
736 *
737 * fovy - field of view in the y axis, in degrees
738 * aspect - aspect ratio
739 * znear - the near z distance of the projection
740 * zfar - the far z distance of the projection
741 * r - optional 4x4 matrix to store the result in
742 *
743 * Returns:
744 *
745 * If r is specified, returns r after creating the projection matrix.
746 * Otherwise, returns a new 4x4 matrix.
747 */
748 M4x4.makePerspective = function M4x4_makePerspective (fovy, aspect, znear, zfar, r) {
749 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
751 var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
752 var ymin = -ymax;
753 var xmin = ymin * aspect;
754 var xmax = ymax * aspect;
756 return M4x4.makeFrustum(xmin, xmax, ymin, ymax, znear, zfar, r);
757 };
759 /*
760 * Function: M4x4.makeOrtho
761 *
762 * Creates a matrix for an orthogonal frustum projection with the given parameters.
763 *
764 * Parameters:
765 *
766 * left - the left coordinate of the frustum
767 * right- the right coordinate of the frustum
768 * bottom - the bottom coordinate of the frustum
769 * top - the top coordinate of the frustum
770 * znear - the near z distance of the frustum
771 * zfar - the far z distance of the frustum
772 * r - optional 4x4 matrix to store the result in
773 *
774 * Returns:
775 *
776 * If r is specified, returns r after creating the projection matrix.
777 * Otherwise, returns a new 4x4 matrix.
778 */
779 M4x4.makeOrtho = function M4x4_makeOrtho (left, right, bottom, top, znear, zfar, r) {
780 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
782 if (r == undefined)
783 r = new MJS_FLOAT_ARRAY_TYPE(16);
785 var tX = -(right+left)/(right-left);
786 var tY = -(top+bottom)/(top-bottom);
787 var tZ = -(zfar+znear)/(zfar-znear);
788 var X = 2 / (right-left);
789 var Y = 2 / (top-bottom);
790 var Z = -2 / (zfar-znear);
792 r[0] = 2 / (right-left);
793 r[1] = 0;
794 r[2] = 0;
795 r[3] = 0;
796 r[4] = 0;
797 r[5] = 2 / (top-bottom);
798 r[6] = 0;
799 r[7] = 0;
800 r[8] = 0;
801 r[9] = 0;
802 r[10] = -2 / (zfar-znear);
803 r[11] = 0;
804 r[12] = -(right+left)/(right-left);
805 r[13] = -(top+bottom)/(top-bottom);
806 r[14] = -(zfar+znear)/(zfar-znear);
807 r[15] = 1;
809 return r;
810 };
812 /*
813 * Function: M4x4.makeOrtho2D
814 *
815 * Creates a matrix for a 2D orthogonal frustum projection with the given parameters.
816 * znear and zfar are assumed to be -1 and 1, respectively.
817 *
818 * Parameters:
819 *
820 * left - the left coordinate of the frustum
821 * right- the right coordinate of the frustum
822 * bottom - the bottom coordinate of the frustum
823 * top - the top coordinate of the frustum
824 * r - optional 4x4 matrix to store the result in
825 *
826 * Returns:
827 *
828 * If r is specified, returns r after creating the projection matrix.
829 * Otherwise, returns a new 4x4 matrix.
830 */
831 M4x4.makeOrtho2D = function M4x4_makeOrtho2D (left, right, bottom, top, r) {
832 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
834 return M4x4.makeOrtho(left, right, bottom, top, -1, 1, r);
835 };
837 /*
838 * Function: M4x4.mul
839 *
840 * Performs r = a * b.
841 *
842 * Parameters:
843 *
844 * a - the first matrix operand
845 * b - the second matrix operand
846 * r - optional 4x4 matrix to store the result in
847 *
848 * Returns:
849 *
850 * If r is specified, returns r after performing the operation.
851 * Otherwise, returns a new 4x4 matrix with the result.
852 */
853 M4x4.mul = function M4x4_mul(a, b, r) {
854 //MathUtils_assert(a.length == 16, "a.length == 16");
855 //MathUtils_assert(b.length == 16, "b.length == 16");
856 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
857 //MathUtils_assert(a != r && b != r, "a != r && b != r");
859 if (r == undefined)
860 r = new MJS_FLOAT_ARRAY_TYPE(16);
862 var a11 = a[0];
863 var a21 = a[1];
864 var a31 = a[2];
865 var a41 = a[3];
866 var a12 = a[4];
867 var a22 = a[5];
868 var a32 = a[6];
869 var a42 = a[7];
870 var a13 = a[8];
871 var a23 = a[9];
872 var a33 = a[10];
873 var a43 = a[11];
874 var a14 = a[12];
875 var a24 = a[13];
876 var a34 = a[14];
877 var a44 = a[15];
879 var b11 = b[0];
880 var b21 = b[1];
881 var b31 = b[2];
882 var b41 = b[3];
883 var b12 = b[4];
884 var b22 = b[5];
885 var b32 = b[6];
886 var b42 = b[7];
887 var b13 = b[8];
888 var b23 = b[9];
889 var b33 = b[10];
890 var b43 = b[11];
891 var b14 = b[12];
892 var b24 = b[13];
893 var b34 = b[14];
894 var b44 = b[15];
896 r[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
897 r[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
898 r[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
899 r[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
900 r[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
901 r[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
902 r[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
903 r[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
904 r[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
905 r[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
906 r[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
907 r[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
908 r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
909 r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
910 r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
911 r[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
913 return r;
914 };
916 /*
917 * Function: M4x4.mulAffine
918 *
919 * Performs r = a * b, assuming a and b are affine (elements 3,7,11,15 = 0,0,0,1)
920 *
921 * Parameters:
922 *
923 * a - the first matrix operand
924 * b - the second matrix operand
925 * r - optional 4x4 matrix to store the result in
926 *
927 * Returns:
928 *
929 * If r is specified, returns r after performing the operation.
930 * Otherwise, returns a new 4x4 matrix with the result.
931 */
932 M4x4.mulAffine = function M4x4_mulAffine(a, b, r) {
933 //MathUtils_assert(a.length == 16, "a.length == 16");
934 //MathUtils_assert(b.length == 16, "b.length == 16");
935 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
936 //MathUtils_assert(a != r && b != r, "a != r && b != r");
938 if (r == undefined)
939 r = new MJS_FLOAT_ARRAY_TYPE(16);
940 var a11 = a[0];
941 var a21 = a[1];
942 var a31 = a[2];
943 var a12 = a[4];
944 var a22 = a[5];
945 var a32 = a[6];
946 var a13 = a[8];
947 var a23 = a[9];
948 var a33 = a[10];
949 var a14 = a[12];
950 var a24 = a[13];
951 var a34 = a[14];
953 var b11 = b[0];
954 var b21 = b[1];
955 var b31 = b[2];
956 var b12 = b[4];
957 var b22 = b[5];
958 var b32 = b[6];
959 var b13 = b[8];
960 var b23 = b[9];
961 var b33 = b[10];
962 var b14 = b[12];
963 var b24 = b[13];
964 var b34 = b[14];
966 r[0] = a11 * b11 + a12 * b21 + a13 * b31;
967 r[1] = a21 * b11 + a22 * b21 + a23 * b31;
968 r[2] = a31 * b11 + a32 * b21 + a33 * b31;
969 r[3] = 0;
970 r[4] = a11 * b12 + a12 * b22 + a13 * b32;
971 r[5] = a21 * b12 + a22 * b22 + a23 * b32;
972 r[6] = a31 * b12 + a32 * b22 + a33 * b32;
973 r[7] = 0;
974 r[8] = a11 * b13 + a12 * b23 + a13 * b33;
975 r[9] = a21 * b13 + a22 * b23 + a23 * b33;
976 r[10] = a31 * b13 + a32 * b23 + a33 * b33;
977 r[11] = 0;
978 r[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14;
979 r[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24;
980 r[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34;
981 r[15] = 1;
983 return r;
984 };
986 /*
987 * Function: M4x4.makeRotate
988 *
989 * Creates a transformation matrix for rotation by angle radians about the 3-element vector axis.
990 *
991 * Parameters:
992 *
993 * angle - the angle of rotation, in radians
994 * axis - the axis around which the rotation is performed, a 3-element vector
995 * r - optional 4x4 matrix to store the result in
996 *
997 * Returns:
998 *
999 * If r is specified, returns r after creating the matrix.
1000 * Otherwise, returns a new 4x4 matrix with the result.
1001 */
1002 M4x4.makeRotate = function M4x4_makeRotate(angle, axis, r) {
1003 //MathUtils_assert(angle.length == 3, "angle.length == 3");
1004 //MathUtils_assert(axis.length == 3, "axis.length == 3");
1005 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1007 if (r == undefined)
1008 r = new MJS_FLOAT_ARRAY_TYPE(16);
1010 axis = V3.normalize(axis, V3._temp1);
1011 var x = axis[0], y = axis[1], z = axis[2];
1012 var c = Math.cos(angle);
1013 var c1 = 1-c;
1014 var s = Math.sin(angle);
1016 r[0] = x*x*c1+c;
1017 r[1] = y*x*c1+z*s;
1018 r[2] = z*x*c1-y*s;
1019 r[3] = 0;
1020 r[4] = x*y*c1-z*s;
1021 r[5] = y*y*c1+c;
1022 r[6] = y*z*c1+x*s;
1023 r[7] = 0;
1024 r[8] = x*z*c1+y*s;
1025 r[9] = y*z*c1-x*s;
1026 r[10] = z*z*c1+c;
1027 r[11] = 0;
1028 r[12] = 0;
1029 r[13] = 0;
1030 r[14] = 0;
1031 r[15] = 1;
1033 return r;
1034 };
1036 /*
1037 * Function: M4x4.rotate
1039 * Concatenates a rotation of angle radians about the axis to the give matrix m.
1041 * Parameters:
1043 * angle - the angle of rotation, in radians
1044 * axis - the axis around which the rotation is performed, a 3-element vector
1045 * m - the matrix to concatenate the rotation to
1046 * r - optional 4x4 matrix to store the result in
1048 * Returns:
1050 * If r is specified, returns r after performing the operation.
1051 * Otherwise, returns a new 4x4 matrix with the result.
1052 */
1053 M4x4.rotate = function M4x4_rotate(angle, axis, m, r) {
1054 //MathUtils_assert(angle.length == 3, "angle.length == 3");
1055 //MathUtils_assert(axis.length == 3, "axis.length == 3");
1056 //MathUtils_assert(m.length == 16, "m.length == 16");
1057 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1059 if (r == undefined)
1060 r = new MJS_FLOAT_ARRAY_TYPE(16);
1061 var a0=axis [0], a1=axis [1], a2=axis [2];
1062 var l = Math.sqrt(a0*a0 + a1*a1 + a2*a2);
1063 var x = a0, y = a1, z = a2;
1064 if (l != 1.0) {
1065 var im = 1.0 / l;
1066 x *= im;
1067 y *= im;
1068 z *= im;
1070 var c = Math.cos(angle);
1071 var c1 = 1-c;
1072 var s = Math.sin(angle);
1073 var xs = x*s;
1074 var ys = y*s;
1075 var zs = z*s;
1076 var xyc1 = x * y * c1;
1077 var xzc1 = x * z * c1;
1078 var yzc1 = y * z * c1;
1080 var m11 = m[0];
1081 var m21 = m[1];
1082 var m31 = m[2];
1083 var m41 = m[3];
1084 var m12 = m[4];
1085 var m22 = m[5];
1086 var m32 = m[6];
1087 var m42 = m[7];
1088 var m13 = m[8];
1089 var m23 = m[9];
1090 var m33 = m[10];
1091 var m43 = m[11];
1093 var t11 = x * x * c1 + c;
1094 var t21 = xyc1 + zs;
1095 var t31 = xzc1 - ys;
1096 var t12 = xyc1 - zs;
1097 var t22 = y * y * c1 + c;
1098 var t32 = yzc1 + xs;
1099 var t13 = xzc1 + ys;
1100 var t23 = yzc1 - xs;
1101 var t33 = z * z * c1 + c;
1103 r[0] = m11 * t11 + m12 * t21 + m13 * t31;
1104 r[1] = m21 * t11 + m22 * t21 + m23 * t31;
1105 r[2] = m31 * t11 + m32 * t21 + m33 * t31;
1106 r[3] = m41 * t11 + m42 * t21 + m43 * t31;
1107 r[4] = m11 * t12 + m12 * t22 + m13 * t32;
1108 r[5] = m21 * t12 + m22 * t22 + m23 * t32;
1109 r[6] = m31 * t12 + m32 * t22 + m33 * t32;
1110 r[7] = m41 * t12 + m42 * t22 + m43 * t32;
1111 r[8] = m11 * t13 + m12 * t23 + m13 * t33;
1112 r[9] = m21 * t13 + m22 * t23 + m23 * t33;
1113 r[10] = m31 * t13 + m32 * t23 + m33 * t33;
1114 r[11] = m41 * t13 + m42 * t23 + m43 * t33;
1115 if (r != m) {
1116 r[12] = m[12];
1117 r[13] = m[13];
1118 r[14] = m[14];
1119 r[15] = m[15];
1121 return r;
1122 };
1124 /*
1125 * Function: M4x4.makeScale3
1127 * Creates a transformation matrix for scaling by 3 scalar values, one for
1128 * each of the x, y, and z directions.
1130 * Parameters:
1132 * x - the scale for the x axis
1133 * y - the scale for the y axis
1134 * z - the scale for the z axis
1135 * r - optional 4x4 matrix to store the result in
1137 * Returns:
1139 * If r is specified, returns r after creating the matrix.
1140 * Otherwise, returns a new 4x4 matrix with the result.
1141 */
1142 M4x4.makeScale3 = function M4x4_makeScale3(x, y, z, r) {
1143 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1145 if (r == undefined)
1146 r = new MJS_FLOAT_ARRAY_TYPE(16);
1148 r[0] = x;
1149 r[1] = 0;
1150 r[2] = 0;
1151 r[3] = 0;
1152 r[4] = 0;
1153 r[5] = y;
1154 r[6] = 0;
1155 r[7] = 0;
1156 r[8] = 0;
1157 r[9] = 0;
1158 r[10] = z;
1159 r[11] = 0;
1160 r[12] = 0;
1161 r[13] = 0;
1162 r[14] = 0;
1163 r[15] = 1;
1165 return r;
1166 };
1168 /*
1169 * Function: M4x4.makeScale1
1171 * Creates a transformation matrix for a uniform scale by a single scalar value.
1173 * Parameters:
1175 * k - the scale factor
1176 * r - optional 4x4 matrix to store the result in
1178 * Returns:
1180 * If r is specified, returns r after creating the matrix.
1181 * Otherwise, returns a new 4x4 matrix with the result.
1182 */
1183 M4x4.makeScale1 = function M4x4_makeScale1(k, r) {
1184 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1186 return M4x4.makeScale3(k, k, k, r);
1187 };
1189 /*
1190 * Function: M4x4.makeScale
1192 * Creates a transformation matrix for scaling each of the x, y, and z axes by the amount
1193 * given in the corresponding element of the 3-element vector.
1195 * Parameters:
1197 * v - the 3-element vector containing the scale factors
1198 * r - optional 4x4 matrix to store the result in
1200 * Returns:
1202 * If r is specified, returns r after creating the matrix.
1203 * Otherwise, returns a new 4x4 matrix with the result.
1204 */
1205 M4x4.makeScale = function M4x4_makeScale(v, r) {
1206 //MathUtils_assert(v.length == 3, "v.length == 3");
1207 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1209 return M4x4.makeScale3(v[0], v[1], v[2], r);
1210 };
1212 /*
1213 * Function: M4x4.scale3
1214 */
1215 M4x4.scale3 = function M4x4_scale3(x, y, z, m, r) {
1216 //MathUtils_assert(m.length == 16, "m.length == 16");
1217 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1219 if (r == m) {
1220 m[0] *= x;
1221 m[1] *= x;
1222 m[2] *= x;
1223 m[3] *= x;
1224 m[4] *= y;
1225 m[5] *= y;
1226 m[6] *= y;
1227 m[7] *= y;
1228 m[8] *= z;
1229 m[9] *= z;
1230 m[10] *= z;
1231 m[11] *= z;
1232 return m;
1235 if (r == undefined)
1236 r = new MJS_FLOAT_ARRAY_TYPE(16);
1238 r[0] = m[0] * x;
1239 r[1] = m[1] * x;
1240 r[2] = m[2] * x;
1241 r[3] = m[3] * x;
1242 r[4] = m[4] * y;
1243 r[5] = m[5] * y;
1244 r[6] = m[6] * y;
1245 r[7] = m[7] * y;
1246 r[8] = m[8] * z;
1247 r[9] = m[9] * z;
1248 r[10] = m[10] * z;
1249 r[11] = m[11] * z;
1250 r[12] = m[12];
1251 r[13] = m[13];
1252 r[14] = m[14];
1253 r[15] = m[15];
1255 return r;
1256 };
1258 /*
1259 * Function: M4x4.scale1
1260 */
1261 M4x4.scale1 = function M4x4_scale1(k, m, r) {
1262 //MathUtils_assert(m.length == 16, "m.length == 16");
1263 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1264 if (r == m) {
1265 m[0] *= k;
1266 m[1] *= k;
1267 m[2] *= k;
1268 m[3] *= k;
1269 m[4] *= k;
1270 m[5] *= k;
1271 m[6] *= k;
1272 m[7] *= k;
1273 m[8] *= k;
1274 m[9] *= k;
1275 m[10] *= k;
1276 m[11] *= k;
1277 return m;
1281 if (r == undefined)
1282 r = new MJS_FLOAT_ARRAY_TYPE(16);
1284 r[0] = m[0] * k;
1285 r[1] = m[1] * k;
1286 r[2] = m[2] * k;
1287 r[3] = m[3] * k;
1288 r[4] = m[4] * k;
1289 r[5] = m[5] * k;
1290 r[6] = m[6] * k;
1291 r[7] = m[7] * k;
1292 r[8] = m[8] * k;
1293 r[9] = m[9] * k;
1294 r[10] = m[10] * k;
1295 r[11] = m[11] * k;
1296 r[12] = m[12];
1297 r[13] = m[13];
1298 r[14] = m[14];
1299 r[15] = m[15];
1301 return r;
1302 };
1304 /*
1305 * Function: M4x4.scale1
1306 */
1307 M4x4.scale = function M4x4_scale(v, m, r) {
1308 //MathUtils_assert(v.length == 3, "v.length == 3");
1309 //MathUtils_assert(m.length == 16, "m.length == 16");
1310 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1311 var x = v[0], y = v[1], z = v[2];
1313 if (r == m) {
1314 m[0] *= x;
1315 m[1] *= x;
1316 m[2] *= x;
1317 m[3] *= x;
1318 m[4] *= y;
1319 m[5] *= y;
1320 m[6] *= y;
1321 m[7] *= y;
1322 m[8] *= z;
1323 m[9] *= z;
1324 m[10] *= z;
1325 m[11] *= z;
1326 return m;
1329 if (r == undefined)
1330 r = new MJS_FLOAT_ARRAY_TYPE(16);
1333 r[0] = m[0] * x;
1334 r[1] = m[1] * x;
1335 r[2] = m[2] * x;
1336 r[3] = m[3] * x;
1337 r[4] = m[4] * y;
1338 r[5] = m[5] * y;
1339 r[6] = m[6] * y;
1340 r[7] = m[7] * y;
1341 r[8] = m[8] * z;
1342 r[9] = m[9] * z;
1343 r[10] = m[10] * z;
1344 r[11] = m[11] * z;
1345 r[12] = m[12];
1346 r[13] = m[13];
1347 r[14] = m[14];
1348 r[15] = m[15];
1350 return r;
1351 };
1353 /*
1354 * Function: M4x4.makeTranslate3
1355 */
1356 M4x4.makeTranslate3 = function M4x4_makeTranslate3(x, y, z, r) {
1357 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1359 if (r == undefined)
1360 r = new MJS_FLOAT_ARRAY_TYPE(16);
1362 r[0] = 1;
1363 r[1] = 0;
1364 r[2] = 0;
1365 r[3] = 0;
1366 r[4] = 0;
1367 r[5] = 1;
1368 r[6] = 0;
1369 r[7] = 0;
1370 r[8] = 0;
1371 r[9] = 0;
1372 r[10] = 1;
1373 r[11] = 0;
1374 r[12] = x;
1375 r[13] = y;
1376 r[14] = z;
1377 r[15] = 1;
1379 return r;
1380 };
1382 /*
1383 * Function: M4x4.makeTranslate1
1384 */
1385 M4x4.makeTranslate1 = function M4x4_makeTranslate1 (k, r) {
1386 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1388 return M4x4.makeTranslate3(k, k, k, r);
1389 };
1391 /*
1392 * Function: M4x4.makeTranslate
1393 */
1394 M4x4.makeTranslate = function M4x4_makeTranslate (v, r) {
1395 //MathUtils_assert(v.length == 3, "v.length == 3");
1396 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1398 return M4x4.makeTranslate3(v[0], v[1], v[2], r);
1399 };
1401 /*
1402 * Function: M4x4.translate3Self
1403 */
1404 M4x4.translate3Self = function M4x4_translate3Self (x, y, z, m) {
1405 //MathUtils_assert(m.length == 16, "m.length == 16");
1406 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1407 m[12] += m[0] * x + m[4] * y + m[8] * z;
1408 m[13] += m[1] * x + m[5] * y + m[9] * z;
1409 m[14] += m[2] * x + m[6] * y + m[10] * z;
1410 m[15] += m[3] * x + m[7] * y + m[11] * z;
1411 return m;
1412 };
1414 /*
1415 * Function: M4x4.translate3
1416 */
1417 M4x4.translate3 = function M4x4_translate3 (x, y, z, m, r) {
1418 //MathUtils_assert(m.length == 16, "m.length == 16");
1419 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1421 if (r == m) {
1422 m[12] += m[0] * x + m[4] * y + m[8] * z;
1423 m[13] += m[1] * x + m[5] * y + m[9] * z;
1424 m[14] += m[2] * x + m[6] * y + m[10] * z;
1425 m[15] += m[3] * x + m[7] * y + m[11] * z;
1426 return m;
1429 if (r == undefined)
1430 r = new MJS_FLOAT_ARRAY_TYPE(16);
1432 var m11 = m[0];
1433 var m21 = m[1];
1434 var m31 = m[2];
1435 var m41 = m[3];
1436 var m12 = m[4];
1437 var m22 = m[5];
1438 var m32 = m[6];
1439 var m42 = m[7];
1440 var m13 = m[8];
1441 var m23 = m[9];
1442 var m33 = m[10];
1443 var m43 = m[11];
1446 r[0] = m11;
1447 r[1] = m21;
1448 r[2] = m31;
1449 r[3] = m41;
1450 r[4] = m12;
1451 r[5] = m22;
1452 r[6] = m32;
1453 r[7] = m42;
1454 r[8] = m13;
1455 r[9] = m23;
1456 r[10] = m33;
1457 r[11] = m43;
1458 r[12] = m11 * x + m12 * y + m13 * z + m[12];
1459 r[13] = m21 * x + m22 * y + m23 * z + m[13];
1460 r[14] = m31 * x + m32 * y + m33 * z + m[14];
1461 r[15] = m41 * x + m42 * y + m43 * z + m[15];
1463 return r;
1464 };
1466 /*
1467 * Function: M4x4.translate1
1468 */
1469 M4x4.translate1 = function M4x4_translate1 (k, m, r) {
1470 //MathUtils_assert(m.length == 16, "m.length == 16");
1471 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1473 return M4x4.translate3(k, k, k, m, r);
1474 };
1475 /*
1476 * Function: M4x4.translateSelf
1477 */
1478 M4x4.translateSelf = function M4x4_translateSelf (v, m) {
1479 //MathUtils_assert(v.length == 3, "v.length == 3");
1480 //MathUtils_assert(m.length == 16, "m.length == 16");
1481 var x=v[0], y=v[1], z=v[2];
1482 m[12] += m[0] * x + m[4] * y + m[8] * z;
1483 m[13] += m[1] * x + m[5] * y + m[9] * z;
1484 m[14] += m[2] * x + m[6] * y + m[10] * z;
1485 m[15] += m[3] * x + m[7] * y + m[11] * z;
1486 return m;
1487 };
1488 /*
1489 * Function: M4x4.translate
1490 */
1491 M4x4.translate = function M4x4_translate (v, m, r) {
1492 //MathUtils_assert(v.length == 3, "v.length == 3");
1493 //MathUtils_assert(m.length == 16, "m.length == 16");
1494 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1495 var x=v[0], y=v[1], z=v[2];
1496 if (r == m) {
1497 m[12] += m[0] * x + m[4] * y + m[8] * z;
1498 m[13] += m[1] * x + m[5] * y + m[9] * z;
1499 m[14] += m[2] * x + m[6] * y + m[10] * z;
1500 m[15] += m[3] * x + m[7] * y + m[11] * z;
1501 return m;
1504 if (r == undefined)
1505 r = new MJS_FLOAT_ARRAY_TYPE(16);
1507 var m11 = m[0];
1508 var m21 = m[1];
1509 var m31 = m[2];
1510 var m41 = m[3];
1511 var m12 = m[4];
1512 var m22 = m[5];
1513 var m32 = m[6];
1514 var m42 = m[7];
1515 var m13 = m[8];
1516 var m23 = m[9];
1517 var m33 = m[10];
1518 var m43 = m[11];
1520 r[0] = m11;
1521 r[1] = m21;
1522 r[2] = m31;
1523 r[3] = m41;
1524 r[4] = m12;
1525 r[5] = m22;
1526 r[6] = m32;
1527 r[7] = m42;
1528 r[8] = m13;
1529 r[9] = m23;
1530 r[10] = m33;
1531 r[11] = m43;
1532 r[12] = m11 * x + m12 * y + m13 * z + m[12];
1533 r[13] = m21 * x + m22 * y + m23 * z + m[13];
1534 r[14] = m31 * x + m32 * y + m33 * z + m[14];
1535 r[15] = m41 * x + m42 * y + m43 * z + m[15];
1537 return r;
1538 };
1540 /*
1541 * Function: M4x4.makeLookAt
1542 */
1543 M4x4.makeLookAt = function M4x4_makeLookAt (eye, center, up, r) {
1544 //MathUtils_assert(eye.length == 3, "eye.length == 3");
1545 //MathUtils_assert(center.length == 3, "center.length == 3");
1546 //MathUtils_assert(up.length == 3, "up.length == 3");
1547 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1549 var z = V3.direction(eye, center, V3._temp1);
1550 var x = V3.normalize(V3.cross(up, z, V3._temp2), V3._temp2);
1551 var y = V3.normalize(V3.cross(z, x, V3._temp3), V3._temp3);
1553 var tm1 = M4x4._temp1;
1554 var tm2 = M4x4._temp2;
1556 tm1[0] = x[0];
1557 tm1[1] = y[0];
1558 tm1[2] = z[0];
1559 tm1[3] = 0;
1560 tm1[4] = x[1];
1561 tm1[5] = y[1];
1562 tm1[6] = z[1];
1563 tm1[7] = 0;
1564 tm1[8] = x[2];
1565 tm1[9] = y[2];
1566 tm1[10] = z[2];
1567 tm1[11] = 0;
1568 tm1[12] = 0;
1569 tm1[13] = 0;
1570 tm1[14] = 0;
1571 tm1[15] = 1;
1573 tm2[0] = 1; tm2[1] = 0; tm2[2] = 0; tm2[3] = 0;
1574 tm2[4] = 0; tm2[5] = 1; tm2[6] = 0; tm2[7] = 0;
1575 tm2[8] = 0; tm2[9] = 0; tm2[10] = 1; tm2[11] = 0;
1576 tm2[12] = -eye[0]; tm2[13] = -eye[1]; tm2[14] = -eye[2]; tm2[15] = 1;
1578 if (r == undefined)
1579 r = new MJS_FLOAT_ARRAY_TYPE(16);
1580 return M4x4.mul(tm1, tm2, r);
1581 };
1583 /*
1584 * Function: M4x4.transposeSelf
1585 */
1586 M4x4.transposeSelf = function M4x4_transposeSelf (m) {
1587 //MathUtils_assert(m.length == 16, "m.length == 16");
1588 var tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1589 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1590 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1591 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1592 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1593 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1594 return m;
1595 };
1596 /*
1597 * Function: M4x4.transpose
1598 */
1599 M4x4.transpose = function M4x4_transpose (m, r) {
1600 //MathUtils_assert(m.length == 16, "m.length == 16");
1601 //MathUtils_assert(r == undefined || r.length == 16, "r == undefined || r.length == 16");
1603 if (m == r) {
1604 var tmp = 0.0;
1605 tmp = m[1]; m[1] = m[4]; m[4] = tmp;
1606 tmp = m[2]; m[2] = m[8]; m[8] = tmp;
1607 tmp = m[3]; m[3] = m[12]; m[12] = tmp;
1608 tmp = m[6]; m[6] = m[9]; m[9] = tmp;
1609 tmp = m[7]; m[7] = m[13]; m[13] = tmp;
1610 tmp = m[11]; m[11] = m[14]; m[14] = tmp;
1611 return m;
1614 if (r == undefined)
1615 r = new MJS_FLOAT_ARRAY_TYPE(16);
1617 r[0] = m[0]; r[1] = m[4]; r[2] = m[8]; r[3] = m[12];
1618 r[4] = m[1]; r[5] = m[5]; r[6] = m[9]; r[7] = m[13];
1619 r[8] = m[2]; r[9] = m[6]; r[10] = m[10]; r[11] = m[14];
1620 r[12] = m[3]; r[13] = m[7]; r[14] = m[11]; r[15] = m[15];
1622 return r;
1623 };
1626 /*
1627 * Function: M4x4.transformPoint
1628 */
1629 M4x4.transformPoint = function M4x4_transformPoint (m, v, r) {
1630 //MathUtils_assert(m.length == 16, "m.length == 16");
1631 //MathUtils_assert(v.length == 3, "v.length == 3");
1632 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1633 if (r == undefined)
1634 r = new MJS_FLOAT_ARRAY_TYPE(3);
1636 var v0 = v[0], v1 = v[1], v2 = v[2];
1638 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1639 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1640 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1641 var w = m[3] * v0 + m[7] * v1 + m[11] * v2 + m[15];
1643 if (w != 1.0) {
1644 r[0] /= w;
1645 r[1] /= w;
1646 r[2] /= w;
1649 return r;
1650 };
1652 /*
1653 * Function: M4x4.transformLine
1654 */
1655 M4x4.transformLine = function M4x4_transformLine(m, v, r) {
1656 //MathUtils_assert(m.length == 16, "m.length == 16");
1657 //MathUtils_assert(v.length == 3, "v.length == 3");
1658 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1659 if (r == undefined)
1660 r = new MJS_FLOAT_ARRAY_TYPE(3);
1662 var v0 = v[0], v1 = v[1], v2 = v[2];
1663 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1664 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1665 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1666 var w = m[3] * v0 + m[7] * v1 + m[11] * v2;
1668 if (w != 1.0) {
1669 r[0] /= w;
1670 r[1] /= w;
1671 r[2] /= w;
1674 return r;
1675 };
1678 /*
1679 * Function: M4x4.transformPointAffine
1680 */
1681 M4x4.transformPointAffine = function M4x4_transformPointAffine (m, v, r) {
1682 //MathUtils_assert(m.length == 16, "m.length == 16");
1683 //MathUtils_assert(v.length == 3, "v.length == 3");
1684 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1685 if (r == undefined)
1686 r = new MJS_FLOAT_ARRAY_TYPE(3);
1688 var v0 = v[0], v1 = v[1], v2 = v[2];
1690 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2 + m[12];
1691 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2 + m[13];
1692 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2 + m[14];
1694 return r;
1695 };
1697 /*
1698 * Function: M4x4.transformLineAffine
1699 */
1700 M4x4.transformLineAffine = function M4x4_transformLineAffine(m, v, r) {
1701 //MathUtils_assert(m.length == 16, "m.length == 16");
1702 //MathUtils_assert(v.length == 3, "v.length == 3");
1703 //MathUtils_assert(r == undefined || r.length == 3, "r == undefined || r.length == 3");
1704 if (r == undefined)
1705 r = new MJS_FLOAT_ARRAY_TYPE(3);
1707 var v0 = v[0], v1 = v[1], v2 = v[2];
1708 r[0] = m[0] * v0 + m[4] * v1 + m[8] * v2;
1709 r[1] = m[1] * v0 + m[5] * v1 + m[9] * v2;
1710 r[2] = m[2] * v0 + m[6] * v1 + m[10] * v2;
1712 return r;
1713 };
1715 M4x4.makeBasis = function M4x4_makeBasis(vx,vy,vz) {
1717 var r = new MJS_FLOAT_ARRAY_TYPE(16);
1719 r[0] = vx[0];
1720 r[1] = vx[1];
1721 r[2] = vx[2];
1722 r[3] = 0;
1723 r[4] = vy[0];
1724 r[5] = vy[1];
1725 r[6] = vy[2];
1726 r[7] = 0;
1727 r[8] = vz[0];
1728 r[9] = vz[1];
1729 r[10] = vz[2];
1730 r[11] = 0;
1731 r[12] = 0;
1732 r[13] = 0;
1733 r[14] = 0;
1734 r[15] = 1;
1736 return r;
1738 };
1740 return {
1741 V3: V3,
1742 v3: F3(V3.$),
1743 toTuple3: V3.toTuple3,
1744 v3add: F2(V3.add),
1745 v3sub: F2(V3.sub),
1746 v3neg: V3.neg,
1747 v3direction: F2(V3.direction),
1748 v3length: V3.length,
1749 v3lengthSquared: V3.lengthSquared,
1750 v3normalize: V3.normalize,
1751 v3scale: F2(V3.scale),
1752 v3dot: F2(V3.dot),
1753 v3cross: F2(V3.cross),
1754 v3mul4x4: F2(V3.mul4x4),
1755 M4x4:M4x4,
1756 m4x4identity: M4x4.identity,
1757 m4x4topLeft3x3: M4x4.topLeft3x3,
1758 m4x4inverseOrthonormal: M4x4.inverseOrthonormal,
1759 m4x4inverseTo3x3: M4x4.inverseTo3x3,
1760 m4x4makeFrustum: F6(M4x4.makeFrustum),
1761 m4x4makePerspective: F4(M4x4.makePerspective),
1762 m4x4makeOrtho: F6(M4x4.makeOrtho),
1763 m4x4makeOrtho2D: F4(M4x4.makeOrtho2D),
1764 m4x4mul: F2(M4x4.mul),
1765 m4x4Affine: F2(M4x4.mulAffine),
1766 m4x4makeRotate: F2(M4x4.makeRotate),
1767 m4x4rotate: F3(M4x4.rotate),
1768 m4x4makeScale3: F3(M4x4.makeScale3),
1769 m4x4makeScale1: M4x4.makeScale1,
1770 m4x4makeScale: M4x4.makeScale,
1771 m4x4scale3: F4(M4x4.scale3),
1772 m4x4scale: F2(M4x4.scale),
1773 m4x4makeTranslate3: F3(M4x4.makeTranslate3),
1774 m4x4makeTranslate: M4x4.makeTranslate,
1775 m4x4translate3: F4(M4x4.translate3),
1776 m4x4translate: F2(M4x4.translate),
1777 m4x4makeLookAt: F3(M4x4.makeLookAt),
1778 m4x4transpose: M4x4.transpose,
1779 m4x4transformPoint: F2(M4x4.transformPoint),
1780 m4x4makeBasis: F3(M4x4.makeBasis),
1781 };