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