Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/src/gl-matrix.js
4128 views
1
(() => {
2
3
/**
4
* @fileoverview gl-matrix - High performance matrix and vector operations for WebGL
5
* @author Brandon Jones
6
* @version 1.2.4
7
*/
8
9
// Modified for emscripten:
10
// - Global scoping etc.
11
// - Disabled some non-closure-compatible javadoc comments.
12
13
/*
14
* Copyright (c) 2011 Brandon Jones
15
*
16
* This software is provided 'as-is', without any express or implied
17
* warranty. In no event will the authors be held liable for any damages
18
* arising from the use of this software.
19
*
20
* Permission is granted to anyone to use this software for any purpose,
21
* including commercial applications, and to alter it and redistribute it
22
* freely, subject to the following restrictions:
23
*
24
* 1. The origin of this software must not be misrepresented; you must not
25
* claim that you wrote the original software. If you use this software
26
* in a product, an acknowledgment in the product documentation would be
27
* appreciated but is not required.
28
*
29
* 2. Altered source versions must be plainly marked as such, and must not
30
* be misrepresented as being the original software.
31
*
32
* 3. This notice may not be removed or altered from any source
33
* distribution.
34
*/
35
36
37
/**
38
* @class 3 Dimensional Vector
39
* @name vec3
40
*/
41
var vec3 = {};
42
43
/**
44
* @class 3x3 Matrix
45
* @name mat3
46
*/
47
var mat3 = {};
48
49
/**
50
* @class 4x4 Matrix
51
* @name mat4
52
*/
53
var mat4 = {};
54
55
/**
56
* @class Quaternion
57
* @name quat4
58
*/
59
var quat4 = {};
60
61
var MatrixArray = Float32Array;
62
63
/*
64
* vec3
65
*/
66
67
/**
68
* Creates a new instance of a vec3 using the default array type
69
* Any javascript array-like objects containing at least 3 numeric elements can serve as a vec3
70
*
71
* _param {vec3} [vec] vec3 containing values to initialize with
72
*
73
* _returns {vec3} New vec3
74
*/
75
vec3.create = function (vec) {
76
var dest = new MatrixArray(3);
77
78
if (vec) {
79
dest[0] = vec[0];
80
dest[1] = vec[1];
81
dest[2] = vec[2];
82
} else {
83
dest[0] = dest[1] = dest[2] = 0;
84
}
85
86
return dest;
87
};
88
89
/**
90
* Copies the values of one vec3 to another
91
*
92
* _param {vec3} vec vec3 containing values to copy
93
* _param {vec3} dest vec3 receiving copied values
94
*
95
* _returns {vec3} dest
96
*/
97
vec3.set = function (vec, dest) {
98
dest[0] = vec[0];
99
dest[1] = vec[1];
100
dest[2] = vec[2];
101
102
return dest;
103
};
104
105
/**
106
* Performs a vector addition
107
*
108
* _param {vec3} vec First operand
109
* _param {vec3} vec2 Second operand
110
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
111
*
112
* _returns {vec3} dest if specified, vec otherwise
113
*/
114
vec3.add = function (vec, vec2, dest) {
115
if (!dest || vec === dest) {
116
vec[0] += vec2[0];
117
vec[1] += vec2[1];
118
vec[2] += vec2[2];
119
return vec;
120
}
121
122
dest[0] = vec[0] + vec2[0];
123
dest[1] = vec[1] + vec2[1];
124
dest[2] = vec[2] + vec2[2];
125
return dest;
126
};
127
128
/**
129
* Performs a vector subtraction
130
*
131
* _param {vec3} vec First operand
132
* _param {vec3} vec2 Second operand
133
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
134
*
135
* _returns {vec3} dest if specified, vec otherwise
136
*/
137
vec3.subtract = function (vec, vec2, dest) {
138
if (!dest || vec === dest) {
139
vec[0] -= vec2[0];
140
vec[1] -= vec2[1];
141
vec[2] -= vec2[2];
142
return vec;
143
}
144
145
dest[0] = vec[0] - vec2[0];
146
dest[1] = vec[1] - vec2[1];
147
dest[2] = vec[2] - vec2[2];
148
return dest;
149
};
150
151
/**
152
* Performs a vector multiplication
153
*
154
* _param {vec3} vec First operand
155
* _param {vec3} vec2 Second operand
156
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
157
*
158
* _returns {vec3} dest if specified, vec otherwise
159
*/
160
vec3.multiply = function (vec, vec2, dest) {
161
if (!dest || vec === dest) {
162
vec[0] *= vec2[0];
163
vec[1] *= vec2[1];
164
vec[2] *= vec2[2];
165
return vec;
166
}
167
168
dest[0] = vec[0] * vec2[0];
169
dest[1] = vec[1] * vec2[1];
170
dest[2] = vec[2] * vec2[2];
171
return dest;
172
};
173
174
/**
175
* Negates the components of a vec3
176
*
177
* _param {vec3} vec vec3 to negate
178
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
179
*
180
* _returns {vec3} dest if specified, vec otherwise
181
*/
182
vec3.negate = function (vec, dest) {
183
if (!dest) { dest = vec; }
184
185
dest[0] = -vec[0];
186
dest[1] = -vec[1];
187
dest[2] = -vec[2];
188
return dest;
189
};
190
191
/**
192
* Multiplies the components of a vec3 by a scalar value
193
*
194
* _param {vec3} vec vec3 to scale
195
* _param {number} val Value to scale by
196
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
197
*
198
* _returns {vec3} dest if specified, vec otherwise
199
*/
200
vec3.scale = function (vec, val, dest) {
201
if (!dest || vec === dest) {
202
vec[0] *= val;
203
vec[1] *= val;
204
vec[2] *= val;
205
return vec;
206
}
207
208
dest[0] = vec[0] * val;
209
dest[1] = vec[1] * val;
210
dest[2] = vec[2] * val;
211
return dest;
212
};
213
214
/**
215
* Generates a unit vector of the same direction as the provided vec3
216
* If vector length is 0, returns [0, 0, 0]
217
*
218
* _param {vec3} vec vec3 to normalize
219
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
220
*
221
* _returns {vec3} dest if specified, vec otherwise
222
*/
223
vec3.normalize = function (vec, dest) {
224
if (!dest) { dest = vec; }
225
226
var x = vec[0], y = vec[1], z = vec[2],
227
len = Math.sqrt(x * x + y * y + z * z);
228
229
if (!len) {
230
dest[0] = 0;
231
dest[1] = 0;
232
dest[2] = 0;
233
return dest;
234
} else if (len === 1) {
235
dest[0] = x;
236
dest[1] = y;
237
dest[2] = z;
238
return dest;
239
}
240
241
len = 1 / len;
242
dest[0] = x * len;
243
dest[1] = y * len;
244
dest[2] = z * len;
245
return dest;
246
};
247
248
/**
249
* Generates the cross product of two vec3s
250
*
251
* _param {vec3} vec First operand
252
* _param {vec3} vec2 Second operand
253
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
254
*
255
* _returns {vec3} dest if specified, vec otherwise
256
*/
257
vec3.cross = function (vec, vec2, dest) {
258
if (!dest) { dest = vec; }
259
260
var x = vec[0], y = vec[1], z = vec[2],
261
x2 = vec2[0], y2 = vec2[1], z2 = vec2[2];
262
263
dest[0] = y * z2 - z * y2;
264
dest[1] = z * x2 - x * z2;
265
dest[2] = x * y2 - y * x2;
266
return dest;
267
};
268
269
/**
270
* Calculates the length of a vec3
271
*
272
* _param {vec3} vec vec3 to calculate length of
273
*
274
* _returns {number} Length of vec
275
*/
276
vec3.length = function (vec) {
277
var x = vec[0], y = vec[1], z = vec[2];
278
return Math.sqrt(x * x + y * y + z * z);
279
};
280
281
/**
282
* Calculates the dot product of two vec3s
283
*
284
* _param {vec3} vec First operand
285
* _param {vec3} vec2 Second operand
286
*
287
* _returns {number} Dot product of vec and vec2
288
*/
289
vec3.dot = function (vec, vec2) {
290
return vec[0] * vec2[0] + vec[1] * vec2[1] + vec[2] * vec2[2];
291
};
292
293
/**
294
* Generates a unit vector pointing from one vector to another
295
*
296
* _param {vec3} vec Origin vec3
297
* _param {vec3} vec2 vec3 to point to
298
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
299
*
300
* _returns {vec3} dest if specified, vec otherwise
301
*/
302
vec3.direction = function (vec, vec2, dest) {
303
if (!dest) { dest = vec; }
304
305
var x = vec[0] - vec2[0],
306
y = vec[1] - vec2[1],
307
z = vec[2] - vec2[2],
308
len = Math.sqrt(x * x + y * y + z * z);
309
310
if (!len) {
311
dest[0] = 0;
312
dest[1] = 0;
313
dest[2] = 0;
314
return dest;
315
}
316
317
len = 1 / len;
318
dest[0] = x * len;
319
dest[1] = y * len;
320
dest[2] = z * len;
321
return dest;
322
};
323
324
/**
325
* Performs a linear interpolation between two vec3
326
*
327
* _param {vec3} vec First vector
328
* _param {vec3} vec2 Second vector
329
* _param {number} lerp Interpolation amount between the two inputs
330
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
331
*
332
* _returns {vec3} dest if specified, vec otherwise
333
*/
334
vec3.lerp = function (vec, vec2, lerp, dest) {
335
if (!dest) { dest = vec; }
336
337
dest[0] = vec[0] + lerp * (vec2[0] - vec[0]);
338
dest[1] = vec[1] + lerp * (vec2[1] - vec[1]);
339
dest[2] = vec[2] + lerp * (vec2[2] - vec[2]);
340
341
return dest;
342
};
343
344
/**
345
* Calculates the euclidean distance between two vec3
346
*
347
* Params:
348
* _param {vec3} vec First vector
349
* _param {vec3} vec2 Second vector
350
*
351
* _returns {number} Distance between vec and vec2
352
*/
353
vec3.dist = function (vec, vec2) {
354
var x = vec2[0] - vec[0],
355
y = vec2[1] - vec[1],
356
z = vec2[2] - vec[2];
357
358
return Math.sqrt(x*x + y*y + z*z);
359
};
360
361
/**
362
* Projects the specified vec3 from screen space into object space
363
* Based on the <a href="http://webcvs.freedesktop.org/mesa/Mesa/src/glu/mesa/project.c?revision=1.4&view=markup">Mesa gluUnProject implementation</a>
364
*
365
* _param {vec3} vec Screen-space vector to project
366
* _param {mat4} view View matrix
367
* _param {mat4} proj Projection matrix
368
* _param {vec4} viewport Viewport as given to gl.viewport [x, y, width, height]
369
* _param {vec3} [dest] vec3 receiving unprojected result. If not specified result is written to vec
370
*
371
* _returns {vec3} dest if specified, vec otherwise
372
*/
373
vec3.unproject = function (vec, view, proj, viewport, dest) {
374
if (!dest) { dest = vec; }
375
376
var m = mat4.create();
377
var v = new MatrixArray(4);
378
379
v[0] = (vec[0] - viewport[0]) * 2.0 / viewport[2] - 1.0;
380
v[1] = (vec[1] - viewport[1]) * 2.0 / viewport[3] - 1.0;
381
v[2] = 2.0 * vec[2] - 1.0;
382
v[3] = 1.0;
383
384
mat4.multiply(proj, view, m);
385
if(!mat4.inverse(m)) { return null; }
386
387
mat4.multiplyVec4(m, v);
388
if(v[3] === 0.0) { return null; }
389
390
dest[0] = v[0] / v[3];
391
dest[1] = v[1] / v[3];
392
dest[2] = v[2] / v[3];
393
394
return dest;
395
};
396
397
/**
398
* Returns a string representation of a vector
399
*
400
* _param {vec3} vec Vector to represent as a string
401
*
402
* _returns {string} String representation of vec
403
*/
404
vec3.str = function (vec) {
405
return '[' + vec[0] + ', ' + vec[1] + ', ' + vec[2] + ']';
406
};
407
408
/*
409
* mat3
410
*/
411
412
/**
413
* Creates a new instance of a mat3 using the default array type
414
* Any javascript array-like object containing at least 9 numeric elements can serve as a mat3
415
*
416
* _param {mat3} [mat] mat3 containing values to initialize with
417
*
418
* _returns {mat3} New mat3
419
*
420
* @param {Object=} mat
421
*/
422
mat3.create = function (mat) {
423
var dest = new MatrixArray(9);
424
425
if (mat) {
426
dest[0] = mat[0];
427
dest[1] = mat[1];
428
dest[2] = mat[2];
429
dest[3] = mat[3];
430
dest[4] = mat[4];
431
dest[5] = mat[5];
432
dest[6] = mat[6];
433
dest[7] = mat[7];
434
dest[8] = mat[8];
435
}
436
437
return dest;
438
};
439
440
/**
441
* Copies the values of one mat3 to another
442
*
443
* _param {mat3} mat mat3 containing values to copy
444
* _param {mat3} dest mat3 receiving copied values
445
*
446
* _returns {mat3} dest
447
*/
448
mat3.set = function (mat, dest) {
449
dest[0] = mat[0];
450
dest[1] = mat[1];
451
dest[2] = mat[2];
452
dest[3] = mat[3];
453
dest[4] = mat[4];
454
dest[5] = mat[5];
455
dest[6] = mat[6];
456
dest[7] = mat[7];
457
dest[8] = mat[8];
458
return dest;
459
};
460
461
/**
462
* Sets a mat3 to an identity matrix
463
*
464
* _param {mat3} dest mat3 to set
465
*
466
* _returns dest if specified, otherwise a new mat3
467
*/
468
mat3.identity = function (dest) {
469
if (!dest) { dest = mat3.create(); }
470
dest[0] = 1;
471
dest[1] = 0;
472
dest[2] = 0;
473
dest[3] = 0;
474
dest[4] = 1;
475
dest[5] = 0;
476
dest[6] = 0;
477
dest[7] = 0;
478
dest[8] = 1;
479
return dest;
480
};
481
482
/**
483
* Transposes a mat3 (flips the values over the diagonal)
484
*
485
* Params:
486
* _param {mat3} mat mat3 to transpose
487
* _param {mat3} [dest] mat3 receiving transposed values. If not specified result is written to mat
488
*/
489
mat3.transpose = function (mat, dest) {
490
// If we are transposing ourselves we can skip a few steps but have to cache some values
491
if (!dest || mat === dest) {
492
var a01 = mat[1], a02 = mat[2],
493
a12 = mat[5];
494
495
mat[1] = mat[3];
496
mat[2] = mat[6];
497
mat[3] = a01;
498
mat[5] = mat[7];
499
mat[6] = a02;
500
mat[7] = a12;
501
return mat;
502
}
503
504
dest[0] = mat[0];
505
dest[1] = mat[3];
506
dest[2] = mat[6];
507
dest[3] = mat[1];
508
dest[4] = mat[4];
509
dest[5] = mat[7];
510
dest[6] = mat[2];
511
dest[7] = mat[5];
512
dest[8] = mat[8];
513
return dest;
514
};
515
516
/**
517
* Copies the elements of a mat3 into the upper 3x3 elements of a mat4
518
*
519
* _param {mat3} mat mat3 containing values to copy
520
* _param {mat4} [dest] mat4 receiving copied values
521
*
522
* _returns {mat4} dest if specified, a new mat4 otherwise
523
*/
524
mat3.toMat4 = function (mat, dest) {
525
if (!dest) { dest = mat4.create(); }
526
527
dest[15] = 1;
528
dest[14] = 0;
529
dest[13] = 0;
530
dest[12] = 0;
531
532
dest[11] = 0;
533
dest[10] = mat[8];
534
dest[9] = mat[7];
535
dest[8] = mat[6];
536
537
dest[7] = 0;
538
dest[6] = mat[5];
539
dest[5] = mat[4];
540
dest[4] = mat[3];
541
542
dest[3] = 0;
543
dest[2] = mat[2];
544
dest[1] = mat[1];
545
dest[0] = mat[0];
546
547
return dest;
548
};
549
550
/**
551
* Returns a string representation of a mat3
552
*
553
* _param {mat3} mat mat3 to represent as a string
554
*
555
* _param {string} String representation of mat
556
*/
557
mat3.str = function (mat) {
558
return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] +
559
', ' + mat[3] + ', ' + mat[4] + ', ' + mat[5] +
560
', ' + mat[6] + ', ' + mat[7] + ', ' + mat[8] + ']';
561
};
562
563
/*
564
* mat4
565
*/
566
567
/**
568
* Creates a new instance of a mat4 using the default array type
569
* Any javascript array-like object containing at least 16 numeric elements can serve as a mat4
570
*
571
* _param {mat4} [mat] mat4 containing values to initialize with
572
*
573
* _returns {mat4} New mat4
574
*
575
* @param {Object=} mat
576
*/
577
mat4.create = function (mat) {
578
var dest = new MatrixArray(16);
579
580
if (mat) {
581
dest[0] = mat[0];
582
dest[1] = mat[1];
583
dest[2] = mat[2];
584
dest[3] = mat[3];
585
dest[4] = mat[4];
586
dest[5] = mat[5];
587
dest[6] = mat[6];
588
dest[7] = mat[7];
589
dest[8] = mat[8];
590
dest[9] = mat[9];
591
dest[10] = mat[10];
592
dest[11] = mat[11];
593
dest[12] = mat[12];
594
dest[13] = mat[13];
595
dest[14] = mat[14];
596
dest[15] = mat[15];
597
}
598
599
return dest;
600
};
601
602
/**
603
* Copies the values of one mat4 to another
604
*
605
* _param {mat4} mat mat4 containing values to copy
606
* _param {mat4} dest mat4 receiving copied values
607
*
608
* _returns {mat4} dest
609
*/
610
mat4.set = function (mat, dest) {
611
dest[0] = mat[0];
612
dest[1] = mat[1];
613
dest[2] = mat[2];
614
dest[3] = mat[3];
615
dest[4] = mat[4];
616
dest[5] = mat[5];
617
dest[6] = mat[6];
618
dest[7] = mat[7];
619
dest[8] = mat[8];
620
dest[9] = mat[9];
621
dest[10] = mat[10];
622
dest[11] = mat[11];
623
dest[12] = mat[12];
624
dest[13] = mat[13];
625
dest[14] = mat[14];
626
dest[15] = mat[15];
627
return dest;
628
};
629
630
/**
631
* Sets a mat4 to an identity matrix
632
*
633
* _param {mat4} dest mat4 to set
634
*
635
* _returns {mat4} dest
636
*/
637
mat4.identity = function (dest) {
638
if (!dest) { dest = mat4.create(); }
639
dest[0] = 1;
640
dest[1] = 0;
641
dest[2] = 0;
642
dest[3] = 0;
643
dest[4] = 0;
644
dest[5] = 1;
645
dest[6] = 0;
646
dest[7] = 0;
647
dest[8] = 0;
648
dest[9] = 0;
649
dest[10] = 1;
650
dest[11] = 0;
651
dest[12] = 0;
652
dest[13] = 0;
653
dest[14] = 0;
654
dest[15] = 1;
655
return dest;
656
};
657
658
/**
659
* Transposes a mat4 (flips the values over the diagonal)
660
*
661
* _param {mat4} mat mat4 to transpose
662
* _param {mat4} [dest] mat4 receiving transposed values. If not specified result is written to mat
663
*/
664
mat4.transpose = function (mat, dest) {
665
// If we are transposing ourselves we can skip a few steps but have to cache some values
666
if (!dest || mat === dest) {
667
var a01 = mat[1], a02 = mat[2], a03 = mat[3],
668
a12 = mat[6], a13 = mat[7],
669
a23 = mat[11];
670
671
mat[1] = mat[4];
672
mat[2] = mat[8];
673
mat[3] = mat[12];
674
mat[4] = a01;
675
mat[6] = mat[9];
676
mat[7] = mat[13];
677
mat[8] = a02;
678
mat[9] = a12;
679
mat[11] = mat[14];
680
mat[12] = a03;
681
mat[13] = a13;
682
mat[14] = a23;
683
return mat;
684
}
685
686
dest[0] = mat[0];
687
dest[1] = mat[4];
688
dest[2] = mat[8];
689
dest[3] = mat[12];
690
dest[4] = mat[1];
691
dest[5] = mat[5];
692
dest[6] = mat[9];
693
dest[7] = mat[13];
694
dest[8] = mat[2];
695
dest[9] = mat[6];
696
dest[10] = mat[10];
697
dest[11] = mat[14];
698
dest[12] = mat[3];
699
dest[13] = mat[7];
700
dest[14] = mat[11];
701
dest[15] = mat[15];
702
return dest;
703
};
704
705
/**
706
* Calculates the determinant of a mat4
707
*
708
* _param {mat4} mat mat4 to calculate determinant of
709
*
710
* _returns {number} determinant of mat
711
*/
712
mat4.determinant = function (mat) {
713
// Cache the matrix values (makes for huge speed increases!)
714
var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3],
715
a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7],
716
a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11],
717
a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
718
719
return (a30 * a21 * a12 * a03 - a20 * a31 * a12 * a03 - a30 * a11 * a22 * a03 + a10 * a31 * a22 * a03 +
720
a20 * a11 * a32 * a03 - a10 * a21 * a32 * a03 - a30 * a21 * a02 * a13 + a20 * a31 * a02 * a13 +
721
a30 * a01 * a22 * a13 - a00 * a31 * a22 * a13 - a20 * a01 * a32 * a13 + a00 * a21 * a32 * a13 +
722
a30 * a11 * a02 * a23 - a10 * a31 * a02 * a23 - a30 * a01 * a12 * a23 + a00 * a31 * a12 * a23 +
723
a10 * a01 * a32 * a23 - a00 * a11 * a32 * a23 - a20 * a11 * a02 * a33 + a10 * a21 * a02 * a33 +
724
a20 * a01 * a12 * a33 - a00 * a21 * a12 * a33 - a10 * a01 * a22 * a33 + a00 * a11 * a22 * a33);
725
};
726
727
/**
728
* Calculates the inverse matrix of a mat4
729
*
730
* _param {mat4} mat mat4 to calculate inverse of
731
* _param {mat4} [dest] mat4 receiving inverse matrix. If not specified result is written to mat, null if matrix cannot be inverted
732
*
733
* @param {Object=} dest
734
*/
735
mat4.inverse = function (mat, dest) {
736
if (!dest) { dest = mat; }
737
738
// Cache the matrix values (makes for huge speed increases!)
739
var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3],
740
a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7],
741
a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11],
742
a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15],
743
744
b00 = a00 * a11 - a01 * a10,
745
b01 = a00 * a12 - a02 * a10,
746
b02 = a00 * a13 - a03 * a10,
747
b03 = a01 * a12 - a02 * a11,
748
b04 = a01 * a13 - a03 * a11,
749
b05 = a02 * a13 - a03 * a12,
750
b06 = a20 * a31 - a21 * a30,
751
b07 = a20 * a32 - a22 * a30,
752
b08 = a20 * a33 - a23 * a30,
753
b09 = a21 * a32 - a22 * a31,
754
b10 = a21 * a33 - a23 * a31,
755
b11 = a22 * a33 - a23 * a32,
756
757
d = (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06),
758
invDet;
759
760
// Calculate the determinant
761
if (!d) { return null; }
762
invDet = 1 / d;
763
764
dest[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;
765
dest[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;
766
dest[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;
767
dest[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;
768
dest[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;
769
dest[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;
770
dest[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;
771
dest[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;
772
dest[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;
773
dest[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;
774
dest[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;
775
dest[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;
776
dest[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;
777
dest[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;
778
dest[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;
779
dest[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;
780
781
return dest;
782
};
783
784
/**
785
* Copies the upper 3x3 elements of a mat4 into another mat4
786
*
787
* _param {mat4} mat mat4 containing values to copy
788
* _param {mat4} [dest] mat4 receiving copied values
789
*
790
* _returns {mat4} dest is specified, a new mat4 otherwise
791
*/
792
mat4.toRotationMat = function (mat, dest) {
793
if (!dest) { dest = mat4.create(); }
794
795
dest[0] = mat[0];
796
dest[1] = mat[1];
797
dest[2] = mat[2];
798
dest[3] = mat[3];
799
dest[4] = mat[4];
800
dest[5] = mat[5];
801
dest[6] = mat[6];
802
dest[7] = mat[7];
803
dest[8] = mat[8];
804
dest[9] = mat[9];
805
dest[10] = mat[10];
806
dest[11] = mat[11];
807
dest[12] = 0;
808
dest[13] = 0;
809
dest[14] = 0;
810
dest[15] = 1;
811
812
return dest;
813
};
814
815
/**
816
* Copies the upper 3x3 elements of a mat4 into a mat3
817
*
818
* _param {mat4} mat mat4 containing values to copy
819
* _param {mat3} [dest] mat3 receiving copied values
820
*
821
* _returns {mat3} dest is specified, a new mat3 otherwise
822
*/
823
mat4.toMat3 = function (mat, dest) {
824
if (!dest) { dest = mat3.create(); }
825
826
dest[0] = mat[0];
827
dest[1] = mat[1];
828
dest[2] = mat[2];
829
dest[3] = mat[4];
830
dest[4] = mat[5];
831
dest[5] = mat[6];
832
dest[6] = mat[8];
833
dest[7] = mat[9];
834
dest[8] = mat[10];
835
836
return dest;
837
};
838
839
/**
840
* Calculates the inverse of the upper 3x3 elements of a mat4 and copies the result into a mat3
841
* The resulting matrix is useful for calculating transformed normals
842
*
843
* Params:
844
* _param {mat4} mat mat4 containing values to invert and copy
845
* _param {mat3} [dest] mat3 receiving values
846
*
847
* _returns {mat3} dest is specified, a new mat3 otherwise, null if the matrix cannot be inverted
848
*/
849
mat4.toInverseMat3 = function (mat, dest) {
850
// Cache the matrix values (makes for huge speed increases!)
851
var a00 = mat[0], a01 = mat[1], a02 = mat[2],
852
a10 = mat[4], a11 = mat[5], a12 = mat[6],
853
a20 = mat[8], a21 = mat[9], a22 = mat[10],
854
855
b01 = a22 * a11 - a12 * a21,
856
b11 = -a22 * a10 + a12 * a20,
857
b21 = a21 * a10 - a11 * a20,
858
859
d = a00 * b01 + a01 * b11 + a02 * b21,
860
id;
861
862
if (!d) { return null; }
863
id = 1 / d;
864
865
if (!dest) { dest = mat3.create(); }
866
867
dest[0] = b01 * id;
868
dest[1] = (-a22 * a01 + a02 * a21) * id;
869
dest[2] = (a12 * a01 - a02 * a11) * id;
870
dest[3] = b11 * id;
871
dest[4] = (a22 * a00 - a02 * a20) * id;
872
dest[5] = (-a12 * a00 + a02 * a10) * id;
873
dest[6] = b21 * id;
874
dest[7] = (-a21 * a00 + a01 * a20) * id;
875
dest[8] = (a11 * a00 - a01 * a10) * id;
876
877
return dest;
878
};
879
880
/**
881
* Performs a matrix multiplication
882
*
883
* _param {mat4} mat First operand
884
* _param {mat4} mat2 Second operand
885
* _param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
886
*/
887
mat4.multiply = function (mat, mat2, dest) {
888
if (!dest) { dest = mat; }
889
890
// Cache the matrix values (makes for huge speed increases!)
891
var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3],
892
a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7],
893
a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11],
894
a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15],
895
896
b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3],
897
b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7],
898
b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11],
899
b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15];
900
901
dest[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
902
dest[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
903
dest[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
904
dest[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
905
dest[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
906
dest[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
907
dest[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
908
dest[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
909
dest[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
910
dest[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
911
dest[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
912
dest[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
913
dest[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
914
dest[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
915
dest[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
916
dest[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
917
918
return dest;
919
};
920
921
/**
922
* Transforms a vec3 with the given matrix
923
* 4th vector component is implicitly '1'
924
*
925
* _param {mat4} mat mat4 to transform the vector with
926
* _param {vec3} vec vec3 to transform
927
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
928
*
929
* _returns {vec3} dest if specified, vec otherwise
930
*/
931
mat4.multiplyVec3 = function (mat, vec, dest) {
932
if (!dest) { dest = vec; }
933
934
var x = vec[0], y = vec[1], z = vec[2];
935
936
dest[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12];
937
dest[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13];
938
dest[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14];
939
940
return dest;
941
};
942
943
/**
944
* Transforms a vec4 with the given matrix
945
*
946
* _param {mat4} mat mat4 to transform the vector with
947
* _param {vec4} vec vec4 to transform
948
* _param {vec4} [dest] vec4 receiving operation result. If not specified result is written to vec
949
*
950
* _returns {vec4} dest if specified, vec otherwise
951
*
952
* @param {Object=} dest
953
*/
954
mat4.multiplyVec4 = function (mat, vec, dest) {
955
if (!dest) { dest = vec; }
956
957
var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
958
959
dest[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12] * w;
960
dest[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13] * w;
961
dest[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14] * w;
962
dest[3] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15] * w;
963
964
return dest;
965
};
966
967
/**
968
* Translates a matrix by the given vector
969
*
970
* _param {mat4} mat mat4 to translate
971
* _param {vec3} vec vec3 specifying the translation
972
* _param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
973
*/
974
mat4.translate = function (mat, vec, dest) {
975
var x = vec[0], y = vec[1], z = vec[2],
976
a00, a01, a02, a03,
977
a10, a11, a12, a13,
978
a20, a21, a22, a23;
979
980
if (!dest || mat === dest) {
981
mat[12] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12];
982
mat[13] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13];
983
mat[14] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14];
984
mat[15] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15];
985
return mat;
986
}
987
988
a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3];
989
a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7];
990
a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11];
991
992
dest[0] = a00; dest[1] = a01; dest[2] = a02; dest[3] = a03;
993
dest[4] = a10; dest[5] = a11; dest[6] = a12; dest[7] = a13;
994
dest[8] = a20; dest[9] = a21; dest[10] = a22; dest[11] = a23;
995
996
dest[12] = a00 * x + a10 * y + a20 * z + mat[12];
997
dest[13] = a01 * x + a11 * y + a21 * z + mat[13];
998
dest[14] = a02 * x + a12 * y + a22 * z + mat[14];
999
dest[15] = a03 * x + a13 * y + a23 * z + mat[15];
1000
return dest;
1001
};
1002
1003
/**
1004
* Scales a matrix by the given vector
1005
*
1006
* _param {mat4} mat mat4 to scale
1007
* _param {vec3} vec vec3 specifying the scale for each axis
1008
* _param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1009
*/
1010
mat4.scale = function (mat, vec, dest) {
1011
var x = vec[0], y = vec[1], z = vec[2];
1012
1013
if (!dest || mat === dest) {
1014
mat[0] *= x;
1015
mat[1] *= x;
1016
mat[2] *= x;
1017
mat[3] *= x;
1018
mat[4] *= y;
1019
mat[5] *= y;
1020
mat[6] *= y;
1021
mat[7] *= y;
1022
mat[8] *= z;
1023
mat[9] *= z;
1024
mat[10] *= z;
1025
mat[11] *= z;
1026
return mat;
1027
}
1028
1029
dest[0] = mat[0] * x;
1030
dest[1] = mat[1] * x;
1031
dest[2] = mat[2] * x;
1032
dest[3] = mat[3] * x;
1033
dest[4] = mat[4] * y;
1034
dest[5] = mat[5] * y;
1035
dest[6] = mat[6] * y;
1036
dest[7] = mat[7] * y;
1037
dest[8] = mat[8] * z;
1038
dest[9] = mat[9] * z;
1039
dest[10] = mat[10] * z;
1040
dest[11] = mat[11] * z;
1041
dest[12] = mat[12];
1042
dest[13] = mat[13];
1043
dest[14] = mat[14];
1044
dest[15] = mat[15];
1045
return dest;
1046
};
1047
1048
/**
1049
* Rotates a matrix by the given angle around the specified axis
1050
* If rotating around a primary axis (X,Y,Z) one of the specialized rotation functions should be used instead for performance
1051
*
1052
* _param {mat4} mat mat4 to rotate
1053
* _param {number} angle Angle (in radians) to rotate
1054
* _param {vec3} axis vec3 representing the axis to rotate around
1055
* _param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1056
*/
1057
mat4.rotate = function (mat, angle, axis, dest) {
1058
var x = axis[0], y = axis[1], z = axis[2],
1059
len = Math.sqrt(x * x + y * y + z * z),
1060
s, c, t,
1061
a00, a01, a02, a03,
1062
a10, a11, a12, a13,
1063
a20, a21, a22, a23,
1064
b00, b01, b02,
1065
b10, b11, b12,
1066
b20, b21, b22;
1067
1068
if (!len) { return null; }
1069
if (len !== 1) {
1070
len = 1 / len;
1071
x *= len;
1072
y *= len;
1073
z *= len;
1074
}
1075
1076
s = Math.sin(angle);
1077
c = Math.cos(angle);
1078
t = 1 - c;
1079
1080
a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3];
1081
a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7];
1082
a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11];
1083
1084
// Construct the elements of the rotation matrix
1085
b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
1086
b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
1087
b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
1088
1089
if (!dest) {
1090
dest = mat;
1091
} else if (mat !== dest) { // If the source and destination differ, copy the unchanged last row
1092
dest[12] = mat[12];
1093
dest[13] = mat[13];
1094
dest[14] = mat[14];
1095
dest[15] = mat[15];
1096
}
1097
1098
// Perform rotation-specific matrix multiplication
1099
dest[0] = a00 * b00 + a10 * b01 + a20 * b02;
1100
dest[1] = a01 * b00 + a11 * b01 + a21 * b02;
1101
dest[2] = a02 * b00 + a12 * b01 + a22 * b02;
1102
dest[3] = a03 * b00 + a13 * b01 + a23 * b02;
1103
1104
dest[4] = a00 * b10 + a10 * b11 + a20 * b12;
1105
dest[5] = a01 * b10 + a11 * b11 + a21 * b12;
1106
dest[6] = a02 * b10 + a12 * b11 + a22 * b12;
1107
dest[7] = a03 * b10 + a13 * b11 + a23 * b12;
1108
1109
dest[8] = a00 * b20 + a10 * b21 + a20 * b22;
1110
dest[9] = a01 * b20 + a11 * b21 + a21 * b22;
1111
dest[10] = a02 * b20 + a12 * b21 + a22 * b22;
1112
dest[11] = a03 * b20 + a13 * b21 + a23 * b22;
1113
return dest;
1114
};
1115
1116
/**
1117
* Rotates a matrix by the given angle around the X axis
1118
*
1119
* _param {mat4} mat mat4 to rotate
1120
* _param {number} angle Angle (in radians) to rotate
1121
* _param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1122
*/
1123
mat4.rotateX = function (mat, angle, dest) {
1124
var s = Math.sin(angle),
1125
c = Math.cos(angle),
1126
a10 = mat[4],
1127
a11 = mat[5],
1128
a12 = mat[6],
1129
a13 = mat[7],
1130
a20 = mat[8],
1131
a21 = mat[9],
1132
a22 = mat[10],
1133
a23 = mat[11];
1134
1135
if (!dest) {
1136
dest = mat;
1137
} else if (mat !== dest) { // If the source and destination differ, copy the unchanged rows
1138
dest[0] = mat[0];
1139
dest[1] = mat[1];
1140
dest[2] = mat[2];
1141
dest[3] = mat[3];
1142
1143
dest[12] = mat[12];
1144
dest[13] = mat[13];
1145
dest[14] = mat[14];
1146
dest[15] = mat[15];
1147
}
1148
1149
// Perform axis-specific matrix multiplication
1150
dest[4] = a10 * c + a20 * s;
1151
dest[5] = a11 * c + a21 * s;
1152
dest[6] = a12 * c + a22 * s;
1153
dest[7] = a13 * c + a23 * s;
1154
1155
dest[8] = a10 * -s + a20 * c;
1156
dest[9] = a11 * -s + a21 * c;
1157
dest[10] = a12 * -s + a22 * c;
1158
dest[11] = a13 * -s + a23 * c;
1159
return dest;
1160
};
1161
1162
/**
1163
* Rotates a matrix by the given angle around the Y axis
1164
*
1165
* _param {mat4} mat mat4 to rotate
1166
* _param {number} angle Angle (in radians) to rotate
1167
* _param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1168
*/
1169
mat4.rotateY = function (mat, angle, dest) {
1170
var s = Math.sin(angle),
1171
c = Math.cos(angle),
1172
a00 = mat[0],
1173
a01 = mat[1],
1174
a02 = mat[2],
1175
a03 = mat[3],
1176
a20 = mat[8],
1177
a21 = mat[9],
1178
a22 = mat[10],
1179
a23 = mat[11];
1180
1181
if (!dest) {
1182
dest = mat;
1183
} else if (mat !== dest) { // If the source and destination differ, copy the unchanged rows
1184
dest[4] = mat[4];
1185
dest[5] = mat[5];
1186
dest[6] = mat[6];
1187
dest[7] = mat[7];
1188
1189
dest[12] = mat[12];
1190
dest[13] = mat[13];
1191
dest[14] = mat[14];
1192
dest[15] = mat[15];
1193
}
1194
1195
// Perform axis-specific matrix multiplication
1196
dest[0] = a00 * c + a20 * -s;
1197
dest[1] = a01 * c + a21 * -s;
1198
dest[2] = a02 * c + a22 * -s;
1199
dest[3] = a03 * c + a23 * -s;
1200
1201
dest[8] = a00 * s + a20 * c;
1202
dest[9] = a01 * s + a21 * c;
1203
dest[10] = a02 * s + a22 * c;
1204
dest[11] = a03 * s + a23 * c;
1205
return dest;
1206
};
1207
1208
/**
1209
* Rotates a matrix by the given angle around the Z axis
1210
*
1211
* _param {mat4} mat mat4 to rotate
1212
* _param {number} angle Angle (in radians) to rotate
1213
* _param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
1214
*/
1215
mat4.rotateZ = function (mat, angle, dest) {
1216
var s = Math.sin(angle),
1217
c = Math.cos(angle),
1218
a00 = mat[0],
1219
a01 = mat[1],
1220
a02 = mat[2],
1221
a03 = mat[3],
1222
a10 = mat[4],
1223
a11 = mat[5],
1224
a12 = mat[6],
1225
a13 = mat[7];
1226
1227
if (!dest) {
1228
dest = mat;
1229
} else if (mat !== dest) { // If the source and destination differ, copy the unchanged last row
1230
dest[8] = mat[8];
1231
dest[9] = mat[9];
1232
dest[10] = mat[10];
1233
dest[11] = mat[11];
1234
1235
dest[12] = mat[12];
1236
dest[13] = mat[13];
1237
dest[14] = mat[14];
1238
dest[15] = mat[15];
1239
}
1240
1241
// Perform axis-specific matrix multiplication
1242
dest[0] = a00 * c + a10 * s;
1243
dest[1] = a01 * c + a11 * s;
1244
dest[2] = a02 * c + a12 * s;
1245
dest[3] = a03 * c + a13 * s;
1246
1247
dest[4] = a00 * -s + a10 * c;
1248
dest[5] = a01 * -s + a11 * c;
1249
dest[6] = a02 * -s + a12 * c;
1250
dest[7] = a03 * -s + a13 * c;
1251
1252
return dest;
1253
};
1254
1255
/**
1256
* Generates a frustum matrix with the given bounds
1257
*
1258
* _param {number} left Left bound of the frustum
1259
* _param {number} right Right bound of the frustum
1260
* _param {number} bottom Bottom bound of the frustum
1261
* _param {number} top Top bound of the frustum
1262
* _param {number} near Near bound of the frustum
1263
* _param {number} far Far bound of the frustum
1264
* _param {mat4} [dest] mat4 frustum matrix will be written into
1265
*
1266
* _returns {mat4} dest if specified, a new mat4 otherwise
1267
*/
1268
mat4.frustum = function (left, right, bottom, top, near, far, dest) {
1269
if (!dest) { dest = mat4.create(); }
1270
var rl = (right - left),
1271
tb = (top - bottom),
1272
fn = (far - near);
1273
dest[0] = (near * 2) / rl;
1274
dest[1] = 0;
1275
dest[2] = 0;
1276
dest[3] = 0;
1277
dest[4] = 0;
1278
dest[5] = (near * 2) / tb;
1279
dest[6] = 0;
1280
dest[7] = 0;
1281
dest[8] = (right + left) / rl;
1282
dest[9] = (top + bottom) / tb;
1283
dest[10] = -(far + near) / fn;
1284
dest[11] = -1;
1285
dest[12] = 0;
1286
dest[13] = 0;
1287
dest[14] = -(far * near * 2) / fn;
1288
dest[15] = 0;
1289
return dest;
1290
};
1291
1292
/**
1293
* Generates a perspective projection matrix with the given bounds
1294
*
1295
* _param {number} fovy Vertical field of view
1296
* _param {number} aspect Aspect ratio. typically viewport width/height
1297
* _param {number} near Near bound of the frustum
1298
* _param {number} far Far bound of the frustum
1299
* _param {mat4} [dest] mat4 frustum matrix will be written into
1300
*
1301
* _returns {mat4} dest if specified, a new mat4 otherwise
1302
*/
1303
mat4.perspective = function (fovy, aspect, near, far, dest) {
1304
var top = near * Math.tan(fovy * Math.PI / 360.0),
1305
right = top * aspect;
1306
return mat4.frustum(-right, right, -top, top, near, far, dest);
1307
};
1308
1309
/**
1310
* Generates a orthogonal projection matrix with the given bounds
1311
*
1312
* _param {number} left Left bound of the frustum
1313
* _param {number} right Right bound of the frustum
1314
* _param {number} bottom Bottom bound of the frustum
1315
* _param {number} top Top bound of the frustum
1316
* _param {number} near Near bound of the frustum
1317
* _param {number} far Far bound of the frustum
1318
* _param {mat4} [dest] mat4 frustum matrix will be written into
1319
*
1320
* _returns {mat4} dest if specified, a new mat4 otherwise
1321
*/
1322
mat4.ortho = function (left, right, bottom, top, near, far, dest) {
1323
if (!dest) { dest = mat4.create(); }
1324
var rl = (right - left),
1325
tb = (top - bottom),
1326
fn = (far - near);
1327
dest[0] = 2 / rl;
1328
dest[1] = 0;
1329
dest[2] = 0;
1330
dest[3] = 0;
1331
dest[4] = 0;
1332
dest[5] = 2 / tb;
1333
dest[6] = 0;
1334
dest[7] = 0;
1335
dest[8] = 0;
1336
dest[9] = 0;
1337
dest[10] = -2 / fn;
1338
dest[11] = 0;
1339
dest[12] = -(left + right) / rl;
1340
dest[13] = -(top + bottom) / tb;
1341
dest[14] = -(far + near) / fn;
1342
dest[15] = 1;
1343
return dest;
1344
};
1345
1346
/**
1347
* Generates a look-at matrix with the given eye position, focal point, and up axis
1348
*
1349
* _param {vec3} eye Position of the viewer
1350
* _param {vec3} center Point the viewer is looking at
1351
* _param {vec3} up vec3 pointing "up"
1352
* _param {mat4} [dest] mat4 frustum matrix will be written into
1353
*
1354
* _returns {mat4} dest if specified, a new mat4 otherwise
1355
*/
1356
mat4.lookAt = function (eye, center, up, dest) {
1357
if (!dest) { dest = mat4.create(); }
1358
1359
var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
1360
eyex = eye[0],
1361
eyey = eye[1],
1362
eyez = eye[2],
1363
upx = up[0],
1364
upy = up[1],
1365
upz = up[2],
1366
centerx = center[0],
1367
centery = center[1],
1368
centerz = center[2];
1369
1370
if (eyex === centerx && eyey === centery && eyez === centerz) {
1371
return mat4.identity(dest);
1372
}
1373
1374
//vec3.direction(eye, center, z);
1375
z0 = eyex - centerx;
1376
z1 = eyey - centery;
1377
z2 = eyez - centerz;
1378
1379
// normalize (no check needed for 0 because of early return)
1380
len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
1381
z0 *= len;
1382
z1 *= len;
1383
z2 *= len;
1384
1385
//vec3.normalize(vec3.cross(up, z, x));
1386
x0 = upy * z2 - upz * z1;
1387
x1 = upz * z0 - upx * z2;
1388
x2 = upx * z1 - upy * z0;
1389
len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
1390
if (!len) {
1391
x0 = 0;
1392
x1 = 0;
1393
x2 = 0;
1394
} else {
1395
len = 1 / len;
1396
x0 *= len;
1397
x1 *= len;
1398
x2 *= len;
1399
}
1400
1401
//vec3.normalize(vec3.cross(z, x, y));
1402
y0 = z1 * x2 - z2 * x1;
1403
y1 = z2 * x0 - z0 * x2;
1404
y2 = z0 * x1 - z1 * x0;
1405
1406
len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
1407
if (!len) {
1408
y0 = 0;
1409
y1 = 0;
1410
y2 = 0;
1411
} else {
1412
len = 1 / len;
1413
y0 *= len;
1414
y1 *= len;
1415
y2 *= len;
1416
}
1417
1418
dest[0] = x0;
1419
dest[1] = y0;
1420
dest[2] = z0;
1421
dest[3] = 0;
1422
dest[4] = x1;
1423
dest[5] = y1;
1424
dest[6] = z1;
1425
dest[7] = 0;
1426
dest[8] = x2;
1427
dest[9] = y2;
1428
dest[10] = z2;
1429
dest[11] = 0;
1430
dest[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
1431
dest[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
1432
dest[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
1433
dest[15] = 1;
1434
1435
return dest;
1436
};
1437
1438
/**
1439
* Creates a matrix from a quaternion rotation and vector translation
1440
* This is equivalent to (but much faster than):
1441
*
1442
* mat4.identity(dest);
1443
* mat4.translate(dest, vec);
1444
* var quatMat = mat4.create();
1445
* quat4.toMat4(quat, quatMat);
1446
* mat4.multiply(dest, quatMat);
1447
*
1448
* _param {quat4} quat Rotation quaternion
1449
* _param {vec3} vec Translation vector
1450
* _param {mat4} [dest] mat4 receiving operation result. If not specified result is written to a new mat4
1451
*
1452
* _returns {mat4} dest if specified, a new mat4 otherwise
1453
*/
1454
mat4.fromRotationTranslation = function (quat, vec, dest) {
1455
if (!dest) { dest = mat4.create(); }
1456
1457
// Quaternion math
1458
var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
1459
x2 = x + x,
1460
y2 = y + y,
1461
z2 = z + z,
1462
1463
xx = x * x2,
1464
xy = x * y2,
1465
xz = x * z2,
1466
yy = y * y2,
1467
yz = y * z2,
1468
zz = z * z2,
1469
wx = w * x2,
1470
wy = w * y2,
1471
wz = w * z2;
1472
1473
dest[0] = 1 - (yy + zz);
1474
dest[1] = xy + wz;
1475
dest[2] = xz - wy;
1476
dest[3] = 0;
1477
dest[4] = xy - wz;
1478
dest[5] = 1 - (xx + zz);
1479
dest[6] = yz + wx;
1480
dest[7] = 0;
1481
dest[8] = xz + wy;
1482
dest[9] = yz - wx;
1483
dest[10] = 1 - (xx + yy);
1484
dest[11] = 0;
1485
dest[12] = vec[0];
1486
dest[13] = vec[1];
1487
dest[14] = vec[2];
1488
dest[15] = 1;
1489
1490
return dest;
1491
};
1492
1493
/**
1494
* Returns a string representation of a mat4
1495
*
1496
* _param {mat4} mat mat4 to represent as a string
1497
*
1498
* _returns {string} String representation of mat
1499
*/
1500
mat4.str = function (mat) {
1501
return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + ', ' + mat[3] +
1502
', ' + mat[4] + ', ' + mat[5] + ', ' + mat[6] + ', ' + mat[7] +
1503
', ' + mat[8] + ', ' + mat[9] + ', ' + mat[10] + ', ' + mat[11] +
1504
', ' + mat[12] + ', ' + mat[13] + ', ' + mat[14] + ', ' + mat[15] + ']';
1505
};
1506
1507
/*
1508
* quat4
1509
*/
1510
1511
/**
1512
* Creates a new instance of a quat4 using the default array type
1513
* Any javascript array containing at least 4 numeric elements can serve as a quat4
1514
*
1515
* _param {quat4} [quat] quat4 containing values to initialize with
1516
*
1517
* _returns {quat4} New quat4
1518
*/
1519
quat4.create = function (quat) {
1520
var dest = new MatrixArray(4);
1521
1522
if (quat) {
1523
dest[0] = quat[0];
1524
dest[1] = quat[1];
1525
dest[2] = quat[2];
1526
dest[3] = quat[3];
1527
}
1528
1529
return dest;
1530
};
1531
1532
/**
1533
* Copies the values of one quat4 to another
1534
*
1535
* _param {quat4} quat quat4 containing values to copy
1536
* _param {quat4} dest quat4 receiving copied values
1537
*
1538
* _returns {quat4} dest
1539
*/
1540
quat4.set = function (quat, dest) {
1541
dest[0] = quat[0];
1542
dest[1] = quat[1];
1543
dest[2] = quat[2];
1544
dest[3] = quat[3];
1545
1546
return dest;
1547
};
1548
1549
/**
1550
* Calculates the W component of a quat4 from the X, Y, and Z components.
1551
* Assumes that quaternion is 1 unit in length.
1552
* Any existing W component will be ignored.
1553
*
1554
* _param {quat4} quat quat4 to calculate W component of
1555
* _param {quat4} [dest] quat4 receiving calculated values. If not specified result is written to quat
1556
*
1557
* _returns {quat4} dest if specified, quat otherwise
1558
*/
1559
quat4.calculateW = function (quat, dest) {
1560
var x = quat[0], y = quat[1], z = quat[2];
1561
1562
if (!dest || quat === dest) {
1563
quat[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
1564
return quat;
1565
}
1566
dest[0] = x;
1567
dest[1] = y;
1568
dest[2] = z;
1569
dest[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
1570
return dest;
1571
};
1572
1573
/**
1574
* Calculates the dot product of two quaternions
1575
*
1576
* _param {quat4} quat First operand
1577
* _param {quat4} quat2 Second operand
1578
*
1579
* @return {number} Dot product of quat and quat2
1580
*/
1581
quat4.dot = function(quat, quat2){
1582
return quat[0]*quat2[0] + quat[1]*quat2[1] + quat[2]*quat2[2] + quat[3]*quat2[3];
1583
};
1584
1585
/**
1586
* Calculates the inverse of a quat4
1587
*
1588
* _param {quat4} quat quat4 to calculate inverse of
1589
* _param {quat4} [dest] quat4 receiving inverse values. If not specified result is written to quat
1590
*
1591
* _returns {quat4} dest if specified, quat otherwise
1592
*/
1593
quat4.inverse = function(quat, dest) {
1594
var q0 = quat[0], q1 = quat[1], q2 = quat[2], q3 = quat[3],
1595
dot = q0*q0 + q1*q1 + q2*q2 + q3*q3,
1596
invDot = dot ? 1.0/dot : 0;
1597
1598
// TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
1599
1600
if(!dest || quat === dest) {
1601
quat[0] *= -invDot;
1602
quat[1] *= -invDot;
1603
quat[2] *= -invDot;
1604
quat[3] *= invDot;
1605
return quat;
1606
}
1607
dest[0] = -quat[0]*invDot;
1608
dest[1] = -quat[1]*invDot;
1609
dest[2] = -quat[2]*invDot;
1610
dest[3] = quat[3]*invDot;
1611
return dest;
1612
};
1613
1614
1615
/**
1616
* Calculates the conjugate of a quat4
1617
* If the quaternion is normalized, this function is faster than quat4.inverse and produces the same result.
1618
*
1619
* _param {quat4} quat quat4 to calculate conjugate of
1620
* _param {quat4} [dest] quat4 receiving conjugate values. If not specified result is written to quat
1621
*
1622
* _returns {quat4} dest if specified, quat otherwise
1623
*/
1624
quat4.conjugate = function (quat, dest) {
1625
if (!dest || quat === dest) {
1626
quat[0] *= -1;
1627
quat[1] *= -1;
1628
quat[2] *= -1;
1629
return quat;
1630
}
1631
dest[0] = -quat[0];
1632
dest[1] = -quat[1];
1633
dest[2] = -quat[2];
1634
dest[3] = quat[3];
1635
return dest;
1636
};
1637
1638
/**
1639
* Calculates the length of a quat4
1640
*
1641
* Params:
1642
* _param {quat4} quat quat4 to calculate length of
1643
*
1644
* _returns Length of quat
1645
*/
1646
quat4.length = function (quat) {
1647
var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
1648
return Math.sqrt(x * x + y * y + z * z + w * w);
1649
};
1650
1651
/**
1652
* Generates a unit quaternion of the same direction as the provided quat4
1653
* If quaternion length is 0, returns [0, 0, 0, 0]
1654
*
1655
* _param {quat4} quat quat4 to normalize
1656
* _param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
1657
*
1658
* _returns {quat4} dest if specified, quat otherwise
1659
*/
1660
quat4.normalize = function (quat, dest) {
1661
if (!dest) { dest = quat; }
1662
1663
var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
1664
len = Math.sqrt(x * x + y * y + z * z + w * w);
1665
if (len === 0) {
1666
dest[0] = 0;
1667
dest[1] = 0;
1668
dest[2] = 0;
1669
dest[3] = 0;
1670
return dest;
1671
}
1672
len = 1 / len;
1673
dest[0] = x * len;
1674
dest[1] = y * len;
1675
dest[2] = z * len;
1676
dest[3] = w * len;
1677
1678
return dest;
1679
};
1680
1681
/**
1682
* Performs quaternion addition
1683
*
1684
* _param {quat4} quat First operand
1685
* _param {quat4} quat2 Second operand
1686
* _param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
1687
*
1688
* _returns {quat4} dest if specified, quat otherwise
1689
*/
1690
quat4.add = function (quat, quat2, dest) {
1691
if(!dest || quat === dest) {
1692
quat[0] += quat2[0];
1693
quat[1] += quat2[1];
1694
quat[2] += quat2[2];
1695
quat[3] += quat2[3];
1696
return quat;
1697
}
1698
dest[0] = quat[0]+quat2[0];
1699
dest[1] = quat[1]+quat2[1];
1700
dest[2] = quat[2]+quat2[2];
1701
dest[3] = quat[3]+quat2[3];
1702
return dest;
1703
};
1704
1705
/**
1706
* Performs a quaternion multiplication
1707
*
1708
* _param {quat4} quat First operand
1709
* _param {quat4} quat2 Second operand
1710
* _param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
1711
*
1712
* _returns {quat4} dest if specified, quat otherwise
1713
*/
1714
quat4.multiply = function (quat, quat2, dest) {
1715
if (!dest) { dest = quat; }
1716
1717
var qax = quat[0], qay = quat[1], qaz = quat[2], qaw = quat[3],
1718
qbx = quat2[0], qby = quat2[1], qbz = quat2[2], qbw = quat2[3];
1719
1720
dest[0] = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
1721
dest[1] = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
1722
dest[2] = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
1723
dest[3] = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
1724
1725
return dest;
1726
};
1727
1728
/**
1729
* Transforms a vec3 with the given quaternion
1730
*
1731
* _param {quat4} quat quat4 to transform the vector with
1732
* _param {vec3} vec vec3 to transform
1733
* _param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
1734
*
1735
* _returns dest if specified, vec otherwise
1736
*/
1737
quat4.multiplyVec3 = function (quat, vec, dest) {
1738
if (!dest) { dest = vec; }
1739
1740
var x = vec[0], y = vec[1], z = vec[2],
1741
qx = quat[0], qy = quat[1], qz = quat[2], qw = quat[3],
1742
1743
// calculate quat * vec
1744
ix = qw * x + qy * z - qz * y,
1745
iy = qw * y + qz * x - qx * z,
1746
iz = qw * z + qx * y - qy * x,
1747
iw = -qx * x - qy * y - qz * z;
1748
1749
// calculate result * inverse quat
1750
dest[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
1751
dest[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
1752
dest[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
1753
1754
return dest;
1755
};
1756
1757
/**
1758
* Multiplies the components of a quaternion by a scalar value
1759
*
1760
* _param {quat4} quat to scale
1761
* _param {number} val Value to scale by
1762
* _param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
1763
*
1764
* _returns {quat4} dest if specified, quat otherwise
1765
*/
1766
quat4.scale = function (quat, val, dest) {
1767
if(!dest || quat === dest) {
1768
quat[0] *= val;
1769
quat[1] *= val;
1770
quat[2] *= val;
1771
quat[3] *= val;
1772
return quat;
1773
}
1774
dest[0] = quat[0]*val;
1775
dest[1] = quat[1]*val;
1776
dest[2] = quat[2]*val;
1777
dest[3] = quat[3]*val;
1778
return dest;
1779
};
1780
1781
/**
1782
* Calculates a 3x3 matrix from the given quat4
1783
*
1784
* _param {quat4} quat quat4 to create matrix from
1785
* _param {mat3} [dest] mat3 receiving operation result
1786
*
1787
* _returns {mat3} dest if specified, a new mat3 otherwise
1788
*/
1789
quat4.toMat3 = function (quat, dest) {
1790
if (!dest) { dest = mat3.create(); }
1791
1792
var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
1793
x2 = x + x,
1794
y2 = y + y,
1795
z2 = z + z,
1796
1797
xx = x * x2,
1798
xy = x * y2,
1799
xz = x * z2,
1800
yy = y * y2,
1801
yz = y * z2,
1802
zz = z * z2,
1803
wx = w * x2,
1804
wy = w * y2,
1805
wz = w * z2;
1806
1807
dest[0] = 1 - (yy + zz);
1808
dest[1] = xy + wz;
1809
dest[2] = xz - wy;
1810
1811
dest[3] = xy - wz;
1812
dest[4] = 1 - (xx + zz);
1813
dest[5] = yz + wx;
1814
1815
dest[6] = xz + wy;
1816
dest[7] = yz - wx;
1817
dest[8] = 1 - (xx + yy);
1818
1819
return dest;
1820
};
1821
1822
/**
1823
* Calculates a 4x4 matrix from the given quat4
1824
*
1825
* _param {quat4} quat quat4 to create matrix from
1826
* _param {mat4} [dest] mat4 receiving operation result
1827
*
1828
* _returns {mat4} dest if specified, a new mat4 otherwise
1829
*/
1830
quat4.toMat4 = function (quat, dest) {
1831
if (!dest) { dest = mat4.create(); }
1832
1833
var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
1834
x2 = x + x,
1835
y2 = y + y,
1836
z2 = z + z,
1837
1838
xx = x * x2,
1839
xy = x * y2,
1840
xz = x * z2,
1841
yy = y * y2,
1842
yz = y * z2,
1843
zz = z * z2,
1844
wx = w * x2,
1845
wy = w * y2,
1846
wz = w * z2;
1847
1848
dest[0] = 1 - (yy + zz);
1849
dest[1] = xy + wz;
1850
dest[2] = xz - wy;
1851
dest[3] = 0;
1852
1853
dest[4] = xy - wz;
1854
dest[5] = 1 - (xx + zz);
1855
dest[6] = yz + wx;
1856
dest[7] = 0;
1857
1858
dest[8] = xz + wy;
1859
dest[9] = yz - wx;
1860
dest[10] = 1 - (xx + yy);
1861
dest[11] = 0;
1862
1863
dest[12] = 0;
1864
dest[13] = 0;
1865
dest[14] = 0;
1866
dest[15] = 1;
1867
1868
return dest;
1869
};
1870
1871
/**
1872
* Performs a spherical linear interpolation between two quat4
1873
*
1874
* _param {quat4} quat First quaternion
1875
* _param {quat4} quat2 Second quaternion
1876
* _param {number} slerp Interpolation amount between the two inputs
1877
* _param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
1878
*
1879
* _returns {quat4} dest if specified, quat otherwise
1880
*/
1881
quat4.slerp = function (quat, quat2, slerp, dest) {
1882
if (!dest) { dest = quat; }
1883
1884
var cosHalfTheta = quat[0] * quat2[0] + quat[1] * quat2[1] + quat[2] * quat2[2] + quat[3] * quat2[3],
1885
halfTheta,
1886
sinHalfTheta,
1887
ratioA,
1888
ratioB;
1889
1890
if (Math.abs(cosHalfTheta) >= 1.0) {
1891
if (dest !== quat) {
1892
dest[0] = quat[0];
1893
dest[1] = quat[1];
1894
dest[2] = quat[2];
1895
dest[3] = quat[3];
1896
}
1897
return dest;
1898
}
1899
1900
halfTheta = Math.acos(cosHalfTheta);
1901
sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
1902
1903
if (Math.abs(sinHalfTheta) < 0.001) {
1904
dest[0] = (quat[0] * 0.5 + quat2[0] * 0.5);
1905
dest[1] = (quat[1] * 0.5 + quat2[1] * 0.5);
1906
dest[2] = (quat[2] * 0.5 + quat2[2] * 0.5);
1907
dest[3] = (quat[3] * 0.5 + quat2[3] * 0.5);
1908
return dest;
1909
}
1910
1911
ratioA = Math.sin((1 - slerp) * halfTheta) / sinHalfTheta;
1912
ratioB = Math.sin(slerp * halfTheta) / sinHalfTheta;
1913
1914
dest[0] = (quat[0] * ratioA + quat2[0] * ratioB);
1915
dest[1] = (quat[1] * ratioA + quat2[1] * ratioB);
1916
dest[2] = (quat[2] * ratioA + quat2[2] * ratioB);
1917
dest[3] = (quat[3] * ratioA + quat2[3] * ratioB);
1918
1919
return dest;
1920
};
1921
1922
/**
1923
* Returns a string representation of a quaternion
1924
*
1925
* _param {quat4} quat quat4 to represent as a string
1926
*
1927
* _returns {string} String representation of quat
1928
*/
1929
quat4.str = function (quat) {
1930
return '[' + quat[0] + ', ' + quat[1] + ', ' + quat[2] + ', ' + quat[3] + ']';
1931
};
1932
1933
1934
return {
1935
vec3: vec3,
1936
mat3: mat3,
1937
mat4: mat4,
1938
quat4: quat4
1939
};
1940
1941
})();
1942
1943
1944