@carbonenginejs/core-math 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/mat4.js ADDED
@@ -0,0 +1,600 @@
1
+ import { mat4 as glMat4, vec3 as glVec3 } from "gl-matrix";
2
+ import { pool } from "./pool.js";
3
+
4
+ const
5
+ mat4 = { ...glMat4 },
6
+ vec3 = { ...glVec3 };
7
+
8
+ export { mat4 };
9
+
10
+ /**
11
+ *
12
+ * @param {mat4} m
13
+ * @param {quat} rotation
14
+ * @param {vec3} translation
15
+ * @param {vec3} scaling
16
+ * @returns {mat4} m
17
+ */
18
+ mat4.decompose = function (m, rotation, translation, scaling)
19
+ {
20
+ mat4.getRotation(rotation, m);
21
+ mat4.getTranslation(translation, m);
22
+ mat4.getScaling(scaling, m);
23
+ return m;
24
+ };
25
+
26
+ /**
27
+ * Allocates a pooled mat4
28
+ * @returns {Float32Array|mat4}
29
+ */
30
+ mat4.alloc = function ()
31
+ {
32
+ return pool.allocF32(16);
33
+ };
34
+
35
+ /**
36
+ * Unallocates a pooled mat4
37
+ * @param {mat4|Float32Array} a
38
+ */
39
+ mat4.unalloc = function (a)
40
+ {
41
+ pool.freeType(a);
42
+ };
43
+
44
+ /**
45
+ * Sets a mat4 from a bone joint mat
46
+ * @param {mat4} out
47
+ * @param {Float32Array} jointMat
48
+ * @param {Number} index
49
+ * @return {mat4}
50
+ */
51
+ mat4.fromJointMatIndex = function (out, jointMat, index)
52
+ {
53
+ if (index >= 0)
54
+ {
55
+ const offset = index * 12;
56
+ out[0] = jointMat[offset];
57
+ out[1] = jointMat[offset + 4];
58
+ out[2] = jointMat[offset + 8];
59
+ out[3] = 0;
60
+ out[4] = jointMat[offset + 1];
61
+ out[5] = jointMat[offset + 5];
62
+ out[6] = jointMat[offset + 9];
63
+ out[7] = 0;
64
+ out[8] = jointMat[offset + 2];
65
+ out[9] = jointMat[offset + 6];
66
+ out[10] = jointMat[offset + 10];
67
+ out[11] = 0;
68
+ out[12] = jointMat[offset + 3];
69
+ out[13] = jointMat[offset + 7];
70
+ out[14] = jointMat[offset + 11];
71
+ out[15] = 1;
72
+ return out;
73
+ }
74
+
75
+ return mat4.identity(out);
76
+ };
77
+
78
+ /**
79
+ * arcFromForward
80
+ * @param {mat4} out
81
+ * @param {vec3} v
82
+ * @return {mat4} out
83
+ */
84
+ mat4.arcFromForward = function (out, v)
85
+ {
86
+ const norm = vec3.normalize(pool.allocF32(3), v);
87
+
88
+ mat4.identity(out);
89
+
90
+ if (norm[2] < -0.99999)
91
+ {
92
+ pool.freeType(norm);
93
+ return out;
94
+ }
95
+
96
+ if (norm[2] > 0.99999)
97
+ {
98
+ out[5] = -1.0;
99
+ out[10] = -1.0;
100
+ pool.freeType(norm);
101
+ return out;
102
+ }
103
+
104
+ const h = (1 + norm[2]) / (norm[0] * norm[0] + norm[1] * norm[1]);
105
+
106
+ out[0] = h * norm[1] * norm[1] - norm[2];
107
+ out[1] = -h * norm[0] * norm[1];
108
+ out[2] = norm[0];
109
+
110
+ out[4] = out[1];
111
+ out[5] = h * norm[0] * norm[0] - norm[2];
112
+ out[6] = norm[1];
113
+
114
+ out[8] = -norm[0];
115
+ out[9] = -norm[1];
116
+ out[10] = -norm[2];
117
+
118
+ pool.freeType(norm);
119
+ return out;
120
+ };
121
+
122
+ /**
123
+ * Copies the translation component from one mat4 to another
124
+ * @param {mat4} out
125
+ * @param {mat4} a
126
+ * @returns {mat4} out
127
+ */
128
+ mat4.copyTranslation = function (out, a)
129
+ {
130
+ out[12] = a[12];
131
+ out[13] = a[13];
132
+ out[14] = a[14];
133
+ return out;
134
+ };
135
+
136
+ /**
137
+ * Sets a mat4 from a mat4
138
+ * @param {mat4} out
139
+ * @param {mat3} m
140
+ * @returns {mat4} out
141
+ */
142
+ mat4.fromMat3 = function (out, m)
143
+ {
144
+ out[0] = m[0];
145
+ out[1] = m[1];
146
+ out[2] = m[2];
147
+ out[4] = m[3];
148
+ out[5] = m[4];
149
+ out[6] = m[5];
150
+ out[8] = m[6];
151
+ out[9] = m[7];
152
+ out[10] = m[8];
153
+ out[3] = out[7] = out[11] = out[12] = out[13] = out[14] = 0;
154
+ out[15] = 1;
155
+ return out;
156
+ };
157
+
158
+ // D3D ortho, depth maps to [0..1]
159
+ mat4.orthoD3D = function(out, l, r, b, t, n, f)
160
+ {
161
+ const
162
+ lr = 1 / (r - l),
163
+ bt = 1 / (t - b),
164
+ nf = 1 / (f - n);
165
+
166
+ out[0] = 2 * lr;
167
+ out[4] = 0;
168
+ out[8] = 0;
169
+ out[12] = -(r + l) * lr;
170
+ out[1] = 0;
171
+ out[5] = 2 * bt;
172
+ out[9] = 0;
173
+ out[13] = -(t + b) * bt;
174
+ out[2] = 0;
175
+ out[6] = 0;
176
+ out[10] = nf;
177
+ out[14] = -n * nf;
178
+ out[3] = 0;
179
+ out[7] = 0;
180
+ out[11] = 0;
181
+ out[15] = 1;
182
+ return out;
183
+ };
184
+
185
+ /**
186
+ * Left-handed look-at (D3D-style): +Z forward
187
+ * Column-major (gl-matrix style)
188
+ */
189
+ mat4.lookAtD3D = function (out, eye, center, up)
190
+ {
191
+ const x = pool.allocF32(3);
192
+ const y = pool.allocF32(3);
193
+ const z = pool.allocF32(3);
194
+
195
+ // z = forward = normalize(center - eye) (LH)
196
+ vec3.subtract(z, center, eye);
197
+
198
+ if (vec3.squaredLength(z) === 0)
199
+ {
200
+ z[2] = 1;
201
+ }
202
+
203
+ vec3.normalize(z, z);
204
+
205
+ // x = normalize(cross(up, z))
206
+ vec3.cross(x, up, z);
207
+
208
+ if (vec3.squaredLength(x) === 0)
209
+ {
210
+ // nudge z slightly if up is parallel
211
+ if (Math.abs(up[2]) === 1) z[0] += 0.0001;
212
+ else z[2] += 0.0001;
213
+
214
+ vec3.normalize(z, z);
215
+ vec3.cross(x, up, z);
216
+ }
217
+
218
+ vec3.normalize(x, x);
219
+
220
+ // y = cross(z, x)
221
+ vec3.cross(y, z, x);
222
+
223
+ // Rotation (axes in columns)
224
+ out[0] = x[0]; out[1] = x[1]; out[2] = x[2]; out[3] = 0;
225
+ out[4] = y[0]; out[5] = y[1]; out[6] = y[2]; out[7] = 0;
226
+ out[8] = z[0]; out[9] = z[1]; out[10] = z[2]; out[11] = 0;
227
+
228
+ // Translation
229
+ out[12] = -vec3.dot(x, eye);
230
+ out[13] = -vec3.dot(y, eye);
231
+ out[14] = -vec3.dot(z, eye);
232
+ out[15] = 1;
233
+
234
+ pool.freeType(x);
235
+ pool.freeType(y);
236
+ pool.freeType(z);
237
+
238
+ return out;
239
+
240
+ // After calling lookAtD3D(out, eye, center, up):
241
+ // Transform center by out and it should land on +Z axis (x≈0, y≈0, z>0).
242
+ // Transform eye by out and it should land at the origin (0,0,0).
243
+ };
244
+
245
+ /**
246
+ * Builds a rotation-only look-at basis
247
+ * OpenGL / RH convention
248
+ * −Z is forward
249
+ * Does NOT touch translation
250
+ * Copies translation (and row 3) from an existing matrix
251
+ * Safe for column-major, gl-matrix layout
252
+ *
253
+ * @param {mat4} out - result
254
+ * @param {mat4} m - source matrix
255
+ * @param {vec3} eye - Position of the viewer
256
+ * @param {vec3} center - Point the viewer is looking at
257
+ * @param {vec3} up - vec3 pointing up
258
+ * @returns {mat4} out
259
+ */
260
+ mat4.setLookRotation = function (out, m, eye, center, up)
261
+ {
262
+ const
263
+ x = pool.allocF32(3),
264
+ y = pool.allocF32(3),
265
+ z = pool.allocF32(3),
266
+ u = pool.allocF32(3); // safeUp
267
+
268
+ // z axis = eye - center (camera backward); -z is forward
269
+ vec3.subtract(z, eye, center);
270
+
271
+ if (vec3.squaredLength(z) === 0)
272
+ {
273
+ // arbitrary (back)
274
+ z[2] = 1;
275
+ }
276
+ vec3.normalize(z, z);
277
+
278
+ // Pick a stable up if the provided up is too aligned with z
279
+ vec3.copy(u, up);
280
+
281
+ // if |dot(up, z)| is ~1 then up × z is unstable
282
+ const dz = Math.abs(u[0] * z[0] + u[1] * z[1] + u[2] * z[2]);
283
+ if (dz > 0.9995)
284
+ {
285
+ // choose an alternate up axis that is not parallel to z
286
+ // try Z axis first, then X axis if needed
287
+ u[0] = 0; u[1] = 0; u[2] = 1;
288
+ const dz2 = Math.abs(u[0] * z[0] + u[1] * z[1] + u[2] * z[2]);
289
+ if (dz2 > 0.9995)
290
+ {
291
+ u[0] = 1; u[1] = 0; u[2] = 0;
292
+ }
293
+ }
294
+
295
+ // x = up × z
296
+ vec3.cross(x, u, z);
297
+
298
+ // Still degenerate? (can happen if 'up' was zero-length etc.)
299
+ if (vec3.squaredLength(x) === 0)
300
+ {
301
+ // fall back to a guaranteed-not-parallel up using z's dominant axis
302
+ if (Math.abs(z[1]) < 0.999)
303
+ {
304
+ u[0] = 0; u[1] = 1; u[2] = 0;
305
+ }
306
+ else
307
+ {
308
+ u[0] = 1; u[1] = 0; u[2] = 0;
309
+ }
310
+ vec3.cross(x, u, z);
311
+ }
312
+
313
+ vec3.normalize(x, x);
314
+
315
+ // y = z × x
316
+ vec3.cross(y, z, x);
317
+
318
+ // write rotation (columns)
319
+ out[0] = x[0]; out[1] = x[1]; out[2] = x[2];
320
+ out[4] = y[0]; out[5] = y[1]; out[6] = y[2];
321
+ out[8] = z[0]; out[9] = z[1]; out[10] = z[2];
322
+
323
+ // copy the rest
324
+ if (out !== m)
325
+ {
326
+ out[3] = m[3];
327
+ out[7] = m[7];
328
+ out[11] = m[11];
329
+ out[12] = m[12];
330
+ out[13] = m[13];
331
+ out[14] = m[14];
332
+ out[15] = m[15];
333
+ }
334
+
335
+ pool.freeType(x);
336
+ pool.freeType(y);
337
+ pool.freeType(z);
338
+ pool.freeType(u);
339
+
340
+ return out;
341
+ };
342
+
343
+ /**
344
+ * Gets a mat4's maximum column axis scale
345
+ *
346
+ * @param {mat4} a - source mat4
347
+ * @returns {number} - maximum axis scale
348
+ */
349
+ mat4.maxScaleOnAxis = function (a)
350
+ {
351
+ let m11 = a[0],
352
+ m12 = a[4],
353
+ m13 = a[8],
354
+ m21 = a[1],
355
+ m22 = a[5],
356
+ m23 = a[9],
357
+ m31 = a[2],
358
+ m32 = a[6],
359
+ m33 = a[10];
360
+
361
+ let x = m11 * m11 + m12 * m12 + m13 * m13,
362
+ y = m21 * m21 + m22 * m22 + m23 * m23,
363
+ z = m31 * m31 + m32 * m32 + m33 * m33;
364
+
365
+ return Math.sqrt(Math.max(x, y, z));
366
+ };
367
+
368
+ /**
369
+ * Sets a left handed co-ordinate system perspective from a right handed co-ordinate system
370
+ * @param {mat4} out - receiving mat4
371
+ * @param {number} fovY - Vertical field of view in radians
372
+ * @param {number} aspect - Aspect ratio. typically viewport width/height
373
+ * @param {number} near - Near bound of the frustum
374
+ * @param {number} far - Far bound of the frustum
375
+ * @returns {mat4} out - receiving mat4
376
+ */
377
+ mat4.perspectiveGL = function (out, fovY, aspect, near, far)
378
+ {
379
+ let fH = Math.tan(fovY / 360 * Math.PI) * near;
380
+ let fW = fH * aspect;
381
+ mat4.frustum(out, -fW, fW, -fH, fH, near, far);
382
+ return out;
383
+ };
384
+
385
+ /**
386
+ * Projects a vector from 3d to 2d space, returning normalized screen space value
387
+ * m should be a projection matrix (or a VP or MVP)
388
+ * @author https://github.com/hughsk/from-3d-to-2d/blob/master/index.js
389
+ * @param {vec3} out - receiving vec3
390
+ * @param {mat4} m - Projection / View Projection
391
+ * @param {vec3} a - the point to project
392
+ * @returns {vec3} out - receiving vec3
393
+ */
394
+ mat4.projectVec3 = function (out, m, a)
395
+ {
396
+ let
397
+ ix = a[0],
398
+ iy = a[1],
399
+ iz = a[2];
400
+
401
+ let ox = m[0] * ix + m[4] * iy + m[8] * iz + m[12],
402
+ oy = m[1] * ix + m[5] * iy + m[9] * iz + m[13],
403
+ oz = m[2] * ix + m[6] * iy + m[10] * iz + m[14],
404
+ ow = m[3] * ix + m[7] * iy + m[11] * iz + m[15];
405
+
406
+ out[0] = (ox / ow + 1) / 2;
407
+ out[1] = (oy / ow + 1) / 2;
408
+ out[2] = (oz / ow + 1) / 2;
409
+ return out;
410
+ };
411
+
412
+
413
+ /**
414
+ * Sets the translation component of a mat4 from a vec3
415
+ * @param {mat4} out
416
+ * @param {vec3} v
417
+ * @returns {mat4} out
418
+ */
419
+ mat4.setTranslation = function (out, v)
420
+ {
421
+ out[12] = v[0];
422
+ out[13] = v[1];
423
+ out[14] = v[2];
424
+ return out;
425
+ };
426
+
427
+ /**
428
+ * Sets the translation component of a mat4 from values
429
+ * @param {mat4} out
430
+ * @param {number} x
431
+ * @param {number} y
432
+ * @param {number} z
433
+ * @returns {mat4} out
434
+ */
435
+ mat4.setTranslationFromValues = function (out, x, y, z)
436
+ {
437
+ out[12] = x;
438
+ out[13] = y;
439
+ out[14] = z;
440
+ return out;
441
+ };
442
+
443
+ /**
444
+ * @author three.js authors
445
+ * @param out
446
+ * @param left
447
+ * @param right
448
+ * @param top
449
+ * @param bottom
450
+ * @param near
451
+ * @param far
452
+ * @returns {*}
453
+ */
454
+ mat4.makePerspective = function (out, left, right, top, bottom, near, far)
455
+ {
456
+ let x = 2 * near / (right - left),
457
+ y = 2 * near / (top - bottom);
458
+
459
+ let a = (right + left) / (right - left),
460
+ b = (top + bottom) / (top - bottom),
461
+ c = -(far + near) / (far - near),
462
+ d = -2 * far * near / (far - near);
463
+
464
+ out[0] = x;
465
+ out[4] = 0;
466
+ out[8] = a;
467
+ out[12] = 0;
468
+
469
+ out[1] = 0;
470
+ out[5] = y;
471
+ out[9] = b;
472
+ out[13] = 0;
473
+
474
+ out[2] = 0;
475
+ out[6] = 0;
476
+ out[10] = c;
477
+ out[14] = d;
478
+
479
+ out[3] = 0;
480
+ out[7] = 0;
481
+ out[11] = -1;
482
+ out[15] = 0;
483
+
484
+ return out;
485
+ };
486
+
487
+ /**
488
+ * @author three.js authors
489
+ * @param out
490
+ * @param left
491
+ * @param right
492
+ * @param top
493
+ * @param bottom
494
+ * @param near
495
+ * @param far
496
+ * @returns {mat4}
497
+ */
498
+ mat4.makeOrthographic = function (out, left, right, top, bottom, near, far)
499
+ {
500
+ let w = 1.0 / (right - left),
501
+ h = 1.0 / (top - bottom),
502
+ p = 1.0 / (far - near);
503
+
504
+ let x = (right + left) * w,
505
+ y = (top + bottom) * h,
506
+ z = (far + near) * p;
507
+
508
+ out[0] = 2 * w;
509
+ out[4] = 0;
510
+ out[8] = 0;
511
+ out[12] = -x;
512
+
513
+ out[1] = 0;
514
+ out[5] = 2 * h;
515
+ out[9] = 0;
516
+ out[13] = -y;
517
+
518
+ out[2] = 0;
519
+ out[6] = 0;
520
+ out[10] = -2 * p;
521
+ out[14] = -z;
522
+
523
+ out[3] = 0;
524
+ out[7] = 0;
525
+ out[11] = 0;
526
+ out[15] = 1;
527
+
528
+ return out;
529
+ };
530
+
531
+ export const {
532
+ add,
533
+ adjoint,
534
+ clone,
535
+ copy,
536
+ create,
537
+ decompose,
538
+ determinant,
539
+ equals,
540
+ exactEquals,
541
+ frob,
542
+ fromQuat,
543
+ fromQuat2,
544
+ fromRotation,
545
+ fromRotationTranslation,
546
+ fromRotationTranslationScale,
547
+ fromRotationTranslationScaleOrigin,
548
+ fromScaling,
549
+ fromTranslation,
550
+ fromValues,
551
+ fromXRotation,
552
+ fromYRotation,
553
+ fromZRotation,
554
+ frustum,
555
+ getRotation,
556
+ getScaling,
557
+ getTranslation,
558
+ identity,
559
+ invert,
560
+ lookAt,
561
+ mul,
562
+ multiply,
563
+ multiplyScalar,
564
+ multiplyScalarAndAdd,
565
+ ortho,
566
+ orthoNO,
567
+ orthoZO,
568
+ perspective,
569
+ perspectiveFromFieldOfView,
570
+ perspectiveNO,
571
+ perspectiveZO,
572
+ rotate,
573
+ rotateX,
574
+ rotateY,
575
+ rotateZ,
576
+ scale,
577
+ set,
578
+ str,
579
+ sub,
580
+ subtract,
581
+ targetTo,
582
+ translate,
583
+ transpose,
584
+ alloc,
585
+ unalloc,
586
+ fromJointMatIndex,
587
+ arcFromForward,
588
+ copyTranslation,
589
+ fromMat3,
590
+ orthoD3D,
591
+ lookAtD3D,
592
+ setLookRotation,
593
+ maxScaleOnAxis,
594
+ perspectiveGL,
595
+ projectVec3,
596
+ setTranslation,
597
+ setTranslationFromValues,
598
+ makePerspective,
599
+ makeOrthographic
600
+ } = mat4;