@vib3code/sdk 2.0.3-canary.183c93e → 2.0.3-canary.1f10a9c
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/package.json +2 -4
- package/src/cli/index.js +59 -5
- package/src/export/SVGExporter.js +9 -5
- package/src/geometry/warp/HypersphereCore.js +53 -24
- package/src/math/Mat4x4.js +272 -128
- package/src/math/Projection.js +57 -7
- package/src/math/Rotor4D.js +33 -27
- package/src/math/Vec4.js +65 -8
- package/src/quantum/QuantumVisualizer.js +28 -0
- package/src/testing/ProjectionClass.test.js +38 -0
- package/src/wasm/WasmLoader.js +11 -6
- package/tools/update_projection.py +109 -0
package/src/math/Mat4x4.js
CHANGED
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
import { Vec4 } from './Vec4.js';
|
|
19
19
|
|
|
20
20
|
export class Mat4x4 {
|
|
21
|
+
/**
|
|
22
|
+
* Internal token to skip initialization during construction
|
|
23
|
+
* @private
|
|
24
|
+
*/
|
|
25
|
+
static UNINITIALIZED = {};
|
|
26
|
+
|
|
21
27
|
/**
|
|
22
28
|
* Create a new 4x4 matrix
|
|
23
29
|
* Default is identity matrix
|
|
@@ -26,6 +32,8 @@ export class Mat4x4 {
|
|
|
26
32
|
constructor(elements = null) {
|
|
27
33
|
this.data = new Float32Array(16);
|
|
28
34
|
|
|
35
|
+
if (elements === Mat4x4.UNINITIALIZED) return;
|
|
36
|
+
|
|
29
37
|
if (elements) {
|
|
30
38
|
if (elements.length !== 16) {
|
|
31
39
|
throw new Error('Mat4x4 requires exactly 16 elements');
|
|
@@ -40,17 +48,25 @@ export class Mat4x4 {
|
|
|
40
48
|
}
|
|
41
49
|
}
|
|
42
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Reset to identity matrix
|
|
53
|
+
* @returns {Mat4x4} this
|
|
54
|
+
*/
|
|
55
|
+
identity() {
|
|
56
|
+
const d = this.data;
|
|
57
|
+
d[0] = 1; d[1] = 0; d[2] = 0; d[3] = 0;
|
|
58
|
+
d[4] = 0; d[5] = 1; d[6] = 0; d[7] = 0;
|
|
59
|
+
d[8] = 0; d[9] = 0; d[10] = 1; d[11] = 0;
|
|
60
|
+
d[12] = 0; d[13] = 0; d[14] = 0; d[15] = 1;
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
|
|
43
64
|
/**
|
|
44
65
|
* Create identity matrix
|
|
45
66
|
* @returns {Mat4x4}
|
|
46
67
|
*/
|
|
47
68
|
static identity() {
|
|
48
|
-
return new Mat4x4(
|
|
49
|
-
1, 0, 0, 0,
|
|
50
|
-
0, 1, 0, 0,
|
|
51
|
-
0, 0, 1, 0,
|
|
52
|
-
0, 0, 0, 1
|
|
53
|
-
]);
|
|
69
|
+
return new Mat4x4();
|
|
54
70
|
}
|
|
55
71
|
|
|
56
72
|
/**
|
|
@@ -58,7 +74,7 @@ export class Mat4x4 {
|
|
|
58
74
|
* @returns {Mat4x4}
|
|
59
75
|
*/
|
|
60
76
|
static zero() {
|
|
61
|
-
return new Mat4x4(
|
|
77
|
+
return new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
62
78
|
}
|
|
63
79
|
|
|
64
80
|
/**
|
|
@@ -161,7 +177,7 @@ export class Mat4x4 {
|
|
|
161
177
|
* @returns {Mat4x4} New matrix = this * m
|
|
162
178
|
*/
|
|
163
179
|
multiply(m, target = null) {
|
|
164
|
-
const out = target || new Mat4x4();
|
|
180
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
165
181
|
const r = out.data;
|
|
166
182
|
const a = this.data;
|
|
167
183
|
const b = m.data;
|
|
@@ -321,7 +337,7 @@ export class Mat4x4 {
|
|
|
321
337
|
* @returns {Mat4x4} New matrix
|
|
322
338
|
*/
|
|
323
339
|
add(m, target = null) {
|
|
324
|
-
const out = target || new Mat4x4();
|
|
340
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
325
341
|
const r = out.data;
|
|
326
342
|
const a = this.data;
|
|
327
343
|
const b = m.data;
|
|
@@ -339,7 +355,7 @@ export class Mat4x4 {
|
|
|
339
355
|
* @returns {Mat4x4} New matrix
|
|
340
356
|
*/
|
|
341
357
|
scale(s, target = null) {
|
|
342
|
-
const out = target || new Mat4x4();
|
|
358
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
343
359
|
const r = out.data;
|
|
344
360
|
const a = this.data;
|
|
345
361
|
|
|
@@ -351,16 +367,23 @@ export class Mat4x4 {
|
|
|
351
367
|
|
|
352
368
|
/**
|
|
353
369
|
* Transpose matrix
|
|
370
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
354
371
|
* @returns {Mat4x4} New transposed matrix
|
|
355
372
|
*/
|
|
356
|
-
transpose() {
|
|
373
|
+
transpose(target = null) {
|
|
357
374
|
const m = this.data;
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
375
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
376
|
+
const r = out.data;
|
|
377
|
+
// If target is same as source, use intermediate or careful swap
|
|
378
|
+
if (target === this) {
|
|
379
|
+
return this.transposeInPlace();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
r[0] = m[0]; r[4] = m[1]; r[8] = m[2]; r[12] = m[3];
|
|
383
|
+
r[1] = m[4]; r[5] = m[5]; r[9] = m[6]; r[13] = m[7];
|
|
384
|
+
r[2] = m[8]; r[6] = m[9]; r[10] = m[10]; r[14] = m[11];
|
|
385
|
+
r[3] = m[12]; r[7] = m[13]; r[11] = m[14]; r[15] = m[15];
|
|
386
|
+
return out;
|
|
364
387
|
}
|
|
365
388
|
|
|
366
389
|
/**
|
|
@@ -411,61 +434,85 @@ export class Mat4x4 {
|
|
|
411
434
|
|
|
412
435
|
/**
|
|
413
436
|
* Calculate inverse matrix
|
|
437
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
414
438
|
* @returns {Mat4x4|null} Inverse matrix or null if singular
|
|
415
439
|
*/
|
|
416
|
-
inverse() {
|
|
440
|
+
inverse(target = null) {
|
|
417
441
|
const m = this.data;
|
|
418
|
-
const
|
|
442
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
443
|
+
const inv = out.data;
|
|
444
|
+
|
|
445
|
+
// Note: For in-place inversion (target === this), we need to be careful.
|
|
446
|
+
// The standard algorithm uses input values for every output cell.
|
|
447
|
+
// We can check for aliasing or use local variables if we wanted full safety,
|
|
448
|
+
// but simplest is to compute to temp if aliased, or just computing to the array directly works
|
|
449
|
+
// IF we cache everything first. But here we are writing to `inv` index by index.
|
|
450
|
+
// If inv === m, writing inv[0] destroys m[0] which is needed for inv[5] etc.
|
|
451
|
+
// So aliasing is NOT safe with this direct write approach.
|
|
452
|
+
|
|
453
|
+
// Handle aliasing by cloning first if needed, or using temp array.
|
|
454
|
+
// Since we want performance, let's detect aliasing.
|
|
455
|
+
let sourceData = m;
|
|
456
|
+
if (target === this) {
|
|
457
|
+
// Copy source data to temp array so we can write to 'this.data' safely
|
|
458
|
+
// We can't avoid allocation entirely in this specific edge case easily without unrolling everything into locals,
|
|
459
|
+
// which is huge for 4x4 inverse.
|
|
460
|
+
// Using a static temp buffer would be unsafe for threading/recursion (not an issue in JS single thread usually but still).
|
|
461
|
+
// Let's just clone the source data for the calculation.
|
|
462
|
+
sourceData = new Float32Array(m);
|
|
463
|
+
}
|
|
419
464
|
|
|
420
|
-
|
|
421
|
-
m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
|
|
465
|
+
const s = sourceData;
|
|
422
466
|
|
|
423
|
-
inv[
|
|
424
|
-
|
|
467
|
+
inv[0] = s[5] * s[10] * s[15] - s[5] * s[11] * s[14] - s[9] * s[6] * s[15] +
|
|
468
|
+
s[9] * s[7] * s[14] + s[13] * s[6] * s[11] - s[13] * s[7] * s[10];
|
|
425
469
|
|
|
426
|
-
inv[
|
|
427
|
-
|
|
470
|
+
inv[4] = -s[4] * s[10] * s[15] + s[4] * s[11] * s[14] + s[8] * s[6] * s[15] -
|
|
471
|
+
s[8] * s[7] * s[14] - s[12] * s[6] * s[11] + s[12] * s[7] * s[10];
|
|
428
472
|
|
|
429
|
-
inv[
|
|
430
|
-
|
|
473
|
+
inv[8] = s[4] * s[9] * s[15] - s[4] * s[11] * s[13] - s[8] * s[5] * s[15] +
|
|
474
|
+
s[8] * s[7] * s[13] + s[12] * s[5] * s[11] - s[12] * s[7] * s[9];
|
|
431
475
|
|
|
432
|
-
inv[
|
|
433
|
-
|
|
476
|
+
inv[12] = -s[4] * s[9] * s[14] + s[4] * s[10] * s[13] + s[8] * s[5] * s[14] -
|
|
477
|
+
s[8] * s[6] * s[13] - s[12] * s[5] * s[10] + s[12] * s[6] * s[9];
|
|
434
478
|
|
|
435
|
-
inv[
|
|
436
|
-
|
|
479
|
+
inv[1] = -s[1] * s[10] * s[15] + s[1] * s[11] * s[14] + s[9] * s[2] * s[15] -
|
|
480
|
+
s[9] * s[3] * s[14] - s[13] * s[2] * s[11] + s[13] * s[3] * s[10];
|
|
437
481
|
|
|
438
|
-
inv[
|
|
439
|
-
|
|
482
|
+
inv[5] = s[0] * s[10] * s[15] - s[0] * s[11] * s[14] - s[8] * s[2] * s[15] +
|
|
483
|
+
s[8] * s[3] * s[14] + s[12] * s[2] * s[11] - s[12] * s[3] * s[10];
|
|
440
484
|
|
|
441
|
-
inv[
|
|
442
|
-
|
|
485
|
+
inv[9] = -s[0] * s[9] * s[15] + s[0] * s[11] * s[13] + s[8] * s[1] * s[15] -
|
|
486
|
+
s[8] * s[3] * s[13] - s[12] * s[1] * s[11] + s[12] * s[3] * s[9];
|
|
443
487
|
|
|
444
|
-
inv[
|
|
445
|
-
|
|
488
|
+
inv[13] = s[0] * s[9] * s[14] - s[0] * s[10] * s[13] - s[8] * s[1] * s[14] +
|
|
489
|
+
s[8] * s[2] * s[13] + s[12] * s[1] * s[10] - s[12] * s[2] * s[9];
|
|
446
490
|
|
|
447
|
-
inv[
|
|
448
|
-
|
|
491
|
+
inv[2] = s[1] * s[6] * s[15] - s[1] * s[7] * s[14] - s[5] * s[2] * s[15] +
|
|
492
|
+
s[5] * s[3] * s[14] + s[13] * s[2] * s[7] - s[13] * s[3] * s[6];
|
|
449
493
|
|
|
450
|
-
inv[
|
|
451
|
-
|
|
494
|
+
inv[6] = -s[0] * s[6] * s[15] + s[0] * s[7] * s[14] + s[4] * s[2] * s[15] -
|
|
495
|
+
s[4] * s[3] * s[14] - s[12] * s[2] * s[7] + s[12] * s[3] * s[6];
|
|
452
496
|
|
|
453
|
-
inv[
|
|
454
|
-
|
|
497
|
+
inv[10] = s[0] * s[5] * s[15] - s[0] * s[7] * s[13] - s[4] * s[1] * s[15] +
|
|
498
|
+
s[4] * s[3] * s[13] + s[12] * s[1] * s[7] - s[12] * s[3] * s[5];
|
|
455
499
|
|
|
456
|
-
inv[
|
|
457
|
-
|
|
500
|
+
inv[14] = -s[0] * s[5] * s[14] + s[0] * s[6] * s[13] + s[4] * s[1] * s[14] -
|
|
501
|
+
s[4] * s[2] * s[13] - s[12] * s[1] * s[6] + s[12] * s[2] * s[5];
|
|
458
502
|
|
|
459
|
-
inv[
|
|
460
|
-
|
|
503
|
+
inv[3] = -s[1] * s[6] * s[11] + s[1] * s[7] * s[10] + s[5] * s[2] * s[11] -
|
|
504
|
+
s[5] * s[3] * s[10] - s[9] * s[2] * s[7] + s[9] * s[3] * s[6];
|
|
461
505
|
|
|
462
|
-
inv[
|
|
463
|
-
|
|
506
|
+
inv[7] = s[0] * s[6] * s[11] - s[0] * s[7] * s[10] - s[4] * s[2] * s[11] +
|
|
507
|
+
s[4] * s[3] * s[10] + s[8] * s[2] * s[7] - s[8] * s[3] * s[6];
|
|
464
508
|
|
|
465
|
-
inv[
|
|
466
|
-
|
|
509
|
+
inv[11] = -s[0] * s[5] * s[11] + s[0] * s[7] * s[9] + s[4] * s[1] * s[11] -
|
|
510
|
+
s[4] * s[3] * s[9] - s[8] * s[1] * s[7] + s[8] * s[3] * s[5];
|
|
467
511
|
|
|
468
|
-
|
|
512
|
+
inv[15] = s[0] * s[5] * s[10] - s[0] * s[6] * s[9] - s[4] * s[1] * s[10] +
|
|
513
|
+
s[4] * s[2] * s[9] + s[8] * s[1] * s[6] - s[8] * s[2] * s[5];
|
|
514
|
+
|
|
515
|
+
const det = s[0] * inv[0] + s[1] * inv[4] + s[2] * inv[8] + s[3] * inv[12];
|
|
469
516
|
|
|
470
517
|
if (Math.abs(det) < 1e-10) {
|
|
471
518
|
return null; // Singular matrix
|
|
@@ -476,7 +523,7 @@ export class Mat4x4 {
|
|
|
476
523
|
inv[i] *= invDet;
|
|
477
524
|
}
|
|
478
525
|
|
|
479
|
-
return
|
|
526
|
+
return out;
|
|
480
527
|
}
|
|
481
528
|
|
|
482
529
|
/**
|
|
@@ -684,98 +731,158 @@ export class Mat4x4 {
|
|
|
684
731
|
/**
|
|
685
732
|
* Create XY plane rotation matrix (standard Z-axis rotation in 3D)
|
|
686
733
|
* @param {number} angle - Rotation angle in radians
|
|
734
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
687
735
|
* @returns {Mat4x4}
|
|
688
736
|
*/
|
|
689
|
-
static rotationXY(angle) {
|
|
737
|
+
static rotationXY(angle, target = null) {
|
|
690
738
|
const c = Math.cos(angle);
|
|
691
739
|
const s = Math.sin(angle);
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
0
|
|
697
|
-
|
|
740
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
741
|
+
const r = out.data;
|
|
742
|
+
|
|
743
|
+
if (target) {
|
|
744
|
+
r[0] = c; r[1] = s; r[2] = 0; r[3] = 0;
|
|
745
|
+
r[4] = -s; r[5] = c; r[6] = 0; r[7] = 0;
|
|
746
|
+
r[8] = 0; r[9] = 0; r[10] = 1; r[11] = 0;
|
|
747
|
+
r[12] = 0; r[13] = 0; r[14] = 0; r[15] = 1;
|
|
748
|
+
} else {
|
|
749
|
+
r[0] = c; r[1] = s;
|
|
750
|
+
r[4] = -s; r[5] = c;
|
|
751
|
+
r[10] = 1;
|
|
752
|
+
r[15] = 1;
|
|
753
|
+
}
|
|
754
|
+
return out;
|
|
698
755
|
}
|
|
699
756
|
|
|
700
757
|
/**
|
|
701
758
|
* Create XZ plane rotation matrix (standard Y-axis rotation in 3D)
|
|
702
759
|
* @param {number} angle - Rotation angle in radians
|
|
760
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
703
761
|
* @returns {Mat4x4}
|
|
704
762
|
*/
|
|
705
|
-
static rotationXZ(angle) {
|
|
763
|
+
static rotationXZ(angle, target = null) {
|
|
706
764
|
const c = Math.cos(angle);
|
|
707
765
|
const s = Math.sin(angle);
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
0
|
|
713
|
-
|
|
766
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
767
|
+
const r = out.data;
|
|
768
|
+
|
|
769
|
+
if (target) {
|
|
770
|
+
r[0] = c; r[1] = 0; r[2] = -s; r[3] = 0;
|
|
771
|
+
r[4] = 0; r[5] = 1; r[6] = 0; r[7] = 0;
|
|
772
|
+
r[8] = s; r[9] = 0; r[10] = c; r[11] = 0;
|
|
773
|
+
r[12] = 0; r[13] = 0; r[14] = 0; r[15] = 1;
|
|
774
|
+
} else {
|
|
775
|
+
r[0] = c; r[2] = -s;
|
|
776
|
+
r[5] = 1;
|
|
777
|
+
r[8] = s; r[10] = c;
|
|
778
|
+
r[15] = 1;
|
|
779
|
+
}
|
|
780
|
+
return out;
|
|
714
781
|
}
|
|
715
782
|
|
|
716
783
|
/**
|
|
717
784
|
* Create YZ plane rotation matrix (standard X-axis rotation in 3D)
|
|
718
785
|
* @param {number} angle - Rotation angle in radians
|
|
786
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
719
787
|
* @returns {Mat4x4}
|
|
720
788
|
*/
|
|
721
|
-
static rotationYZ(angle) {
|
|
789
|
+
static rotationYZ(angle, target = null) {
|
|
722
790
|
const c = Math.cos(angle);
|
|
723
791
|
const s = Math.sin(angle);
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
0
|
|
729
|
-
|
|
792
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
793
|
+
const r = out.data;
|
|
794
|
+
|
|
795
|
+
if (target) {
|
|
796
|
+
r[0] = 1; r[1] = 0; r[2] = 0; r[3] = 0;
|
|
797
|
+
r[4] = 0; r[5] = c; r[6] = s; r[7] = 0;
|
|
798
|
+
r[8] = 0; r[9] = -s; r[10] = c; r[11] = 0;
|
|
799
|
+
r[12] = 0; r[13] = 0; r[14] = 0; r[15] = 1;
|
|
800
|
+
} else {
|
|
801
|
+
r[0] = 1;
|
|
802
|
+
r[5] = c; r[6] = s;
|
|
803
|
+
r[9] = -s; r[10] = c;
|
|
804
|
+
r[15] = 1;
|
|
805
|
+
}
|
|
806
|
+
return out;
|
|
730
807
|
}
|
|
731
808
|
|
|
732
809
|
/**
|
|
733
810
|
* Create XW plane rotation matrix (4D hyperspace rotation)
|
|
734
811
|
* Creates "inside-out" effect when w approaches viewer
|
|
735
812
|
* @param {number} angle - Rotation angle in radians
|
|
813
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
736
814
|
* @returns {Mat4x4}
|
|
737
815
|
*/
|
|
738
|
-
static rotationXW(angle) {
|
|
816
|
+
static rotationXW(angle, target = null) {
|
|
739
817
|
const c = Math.cos(angle);
|
|
740
818
|
const s = Math.sin(angle);
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
819
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
820
|
+
const r = out.data;
|
|
821
|
+
|
|
822
|
+
if (target) {
|
|
823
|
+
r[0] = c; r[1] = 0; r[2] = 0; r[3] = s;
|
|
824
|
+
r[4] = 0; r[5] = 1; r[6] = 0; r[7] = 0;
|
|
825
|
+
r[8] = 0; r[9] = 0; r[10] = 1; r[11] = 0;
|
|
826
|
+
r[12] = -s; r[13] = 0; r[14] = 0; r[15] = c;
|
|
827
|
+
} else {
|
|
828
|
+
r[0] = c; r[3] = s;
|
|
829
|
+
r[5] = 1;
|
|
830
|
+
r[10] = 1;
|
|
831
|
+
r[12] = -s; r[15] = c;
|
|
832
|
+
}
|
|
833
|
+
return out;
|
|
747
834
|
}
|
|
748
835
|
|
|
749
836
|
/**
|
|
750
837
|
* Create YW plane rotation matrix (4D hyperspace rotation)
|
|
751
838
|
* @param {number} angle - Rotation angle in radians
|
|
839
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
752
840
|
* @returns {Mat4x4}
|
|
753
841
|
*/
|
|
754
|
-
static rotationYW(angle) {
|
|
842
|
+
static rotationYW(angle, target = null) {
|
|
755
843
|
const c = Math.cos(angle);
|
|
756
844
|
const s = Math.sin(angle);
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
0
|
|
762
|
-
|
|
845
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
846
|
+
const r = out.data;
|
|
847
|
+
|
|
848
|
+
if (target) {
|
|
849
|
+
r[0] = 1; r[1] = 0; r[2] = 0; r[3] = 0;
|
|
850
|
+
r[4] = 0; r[5] = c; r[6] = 0; r[7] = s;
|
|
851
|
+
r[8] = 0; r[9] = 0; r[10] = 1; r[11] = 0;
|
|
852
|
+
r[12] = 0; r[13] = -s; r[14] = 0; r[15] = c;
|
|
853
|
+
} else {
|
|
854
|
+
r[0] = 1;
|
|
855
|
+
r[5] = c; r[7] = s;
|
|
856
|
+
r[10] = 1;
|
|
857
|
+
r[13] = -s; r[15] = c;
|
|
858
|
+
}
|
|
859
|
+
return out;
|
|
763
860
|
}
|
|
764
861
|
|
|
765
862
|
/**
|
|
766
863
|
* Create ZW plane rotation matrix (4D hyperspace rotation)
|
|
767
864
|
* @param {number} angle - Rotation angle in radians
|
|
865
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
768
866
|
* @returns {Mat4x4}
|
|
769
867
|
*/
|
|
770
|
-
static rotationZW(angle) {
|
|
868
|
+
static rotationZW(angle, target = null) {
|
|
771
869
|
const c = Math.cos(angle);
|
|
772
870
|
const s = Math.sin(angle);
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
0
|
|
778
|
-
|
|
871
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
872
|
+
const r = out.data;
|
|
873
|
+
|
|
874
|
+
if (target) {
|
|
875
|
+
r[0] = 1; r[1] = 0; r[2] = 0; r[3] = 0;
|
|
876
|
+
r[4] = 0; r[5] = 1; r[6] = 0; r[7] = 0;
|
|
877
|
+
r[8] = 0; r[9] = 0; r[10] = c; r[11] = s;
|
|
878
|
+
r[12] = 0; r[13] = 0; r[14] = -s; r[15] = c;
|
|
879
|
+
} else {
|
|
880
|
+
r[0] = 1;
|
|
881
|
+
r[5] = 1;
|
|
882
|
+
r[10] = c; r[11] = s;
|
|
883
|
+
r[14] = -s; r[15] = c;
|
|
884
|
+
}
|
|
885
|
+
return out;
|
|
779
886
|
}
|
|
780
887
|
|
|
781
888
|
/**
|
|
@@ -801,24 +908,58 @@ export class Mat4x4 {
|
|
|
801
908
|
* Create combined rotation matrix from all 6 angles
|
|
802
909
|
* Order: XY, XZ, YZ, XW, YW, ZW
|
|
803
910
|
*
|
|
804
|
-
*
|
|
805
|
-
*
|
|
806
|
-
*
|
|
807
|
-
*
|
|
808
|
-
* @param {number}
|
|
809
|
-
* @param {number} [
|
|
810
|
-
* @param {number} [
|
|
911
|
+
* Supports two signatures:
|
|
912
|
+
* 1. rotationFromAngles(angles, target?)
|
|
913
|
+
* 2. rotationFromAngles(xy, xz, yz, xw, yw, zw, target?)
|
|
914
|
+
*
|
|
915
|
+
* @param {object|number} anglesOrXY - Rotation angles object OR XY angle
|
|
916
|
+
* @param {number|Mat4x4} [xzOrTarget] - XZ angle OR target matrix
|
|
917
|
+
* @param {number} [yz=0] - YZ angle
|
|
918
|
+
* @param {number} [xw=0] - XW angle
|
|
919
|
+
* @param {number} [yw=0] - YW angle
|
|
920
|
+
* @param {number} [zw=0] - ZW angle
|
|
921
|
+
* @param {Mat4x4} [target=null] - Target matrix (if using 6-arg signature)
|
|
811
922
|
* @returns {Mat4x4}
|
|
812
923
|
*/
|
|
813
|
-
static rotationFromAngles(
|
|
814
|
-
let
|
|
924
|
+
static rotationFromAngles(anglesOrXY, xzOrTarget, yz, xw, yw, zw, target) {
|
|
925
|
+
let xy = 0, xz = 0;
|
|
926
|
+
let _yz = 0, _xw = 0, _yw = 0, _zw = 0;
|
|
927
|
+
let out = null;
|
|
928
|
+
|
|
929
|
+
if (typeof anglesOrXY === 'number') {
|
|
930
|
+
// Signature: (xy, xz, yz, xw, yw, zw, target)
|
|
931
|
+
xy = anglesOrXY;
|
|
932
|
+
xz = typeof xzOrTarget === 'number' ? xzOrTarget : 0;
|
|
933
|
+
_yz = yz || 0;
|
|
934
|
+
_xw = xw || 0;
|
|
935
|
+
_yw = yw || 0;
|
|
936
|
+
_zw = zw || 0;
|
|
937
|
+
out = target || null;
|
|
938
|
+
} else {
|
|
939
|
+
// Signature: (angles, target)
|
|
940
|
+
const angles = anglesOrXY || {};
|
|
941
|
+
xy = angles.xy || 0;
|
|
942
|
+
xz = angles.xz || 0;
|
|
943
|
+
_yz = angles.yz || 0;
|
|
944
|
+
_xw = angles.xw || 0;
|
|
945
|
+
_yw = angles.yw || 0;
|
|
946
|
+
_zw = angles.zw || 0;
|
|
947
|
+
// The second argument is the target in this case
|
|
948
|
+
// Use duck typing or check constructor name to avoid circular dependency issues if any
|
|
949
|
+
if (xzOrTarget && typeof xzOrTarget === 'object' && xzOrTarget.data) {
|
|
950
|
+
out = xzOrTarget;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
const result = out || new Mat4x4(); // Default constructor is identity
|
|
955
|
+
if (out) result.identity(); // Reset if reused
|
|
815
956
|
|
|
816
|
-
if (
|
|
817
|
-
if (
|
|
818
|
-
if (
|
|
819
|
-
if (
|
|
820
|
-
if (
|
|
821
|
-
if (
|
|
957
|
+
if (xy) result.rotateXY(xy);
|
|
958
|
+
if (xz) result.rotateXZ(xz);
|
|
959
|
+
if (_yz) result.rotateYZ(_yz);
|
|
960
|
+
if (_xw) result.rotateXW(_xw);
|
|
961
|
+
if (_yw) result.rotateYW(_yw);
|
|
962
|
+
if (_zw) result.rotateZW(_zw);
|
|
822
963
|
|
|
823
964
|
return result;
|
|
824
965
|
}
|
|
@@ -847,12 +988,13 @@ export class Mat4x4 {
|
|
|
847
988
|
* @returns {Mat4x4}
|
|
848
989
|
*/
|
|
849
990
|
static uniformScale(s) {
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
]
|
|
991
|
+
const out = new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
992
|
+
const r = out.data;
|
|
993
|
+
r[0] = s;
|
|
994
|
+
r[5] = s;
|
|
995
|
+
r[10] = s;
|
|
996
|
+
r[15] = s;
|
|
997
|
+
return out;
|
|
856
998
|
}
|
|
857
999
|
|
|
858
1000
|
/**
|
|
@@ -864,12 +1006,13 @@ export class Mat4x4 {
|
|
|
864
1006
|
* @returns {Mat4x4}
|
|
865
1007
|
*/
|
|
866
1008
|
static scale(sx, sy, sz, sw = 1) {
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
]
|
|
1009
|
+
const out = new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
1010
|
+
const r = out.data;
|
|
1011
|
+
r[0] = sx;
|
|
1012
|
+
r[5] = sy;
|
|
1013
|
+
r[10] = sz;
|
|
1014
|
+
r[15] = sw;
|
|
1015
|
+
return out;
|
|
873
1016
|
}
|
|
874
1017
|
|
|
875
1018
|
/**
|
|
@@ -885,12 +1028,13 @@ export class Mat4x4 {
|
|
|
885
1028
|
static translation(tx, ty, tz, tw = 0) {
|
|
886
1029
|
// For true 4D translation, you need 5D homogeneous coordinates
|
|
887
1030
|
// This is a placeholder that adds the translation to the W column
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
]
|
|
1031
|
+
const out = new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
1032
|
+
const r = out.data;
|
|
1033
|
+
r[0] = 1;
|
|
1034
|
+
r[5] = 1;
|
|
1035
|
+
r[10] = 1;
|
|
1036
|
+
r[12] = tx; r[13] = ty; r[14] = tz; r[15] = 1 + tw;
|
|
1037
|
+
return out;
|
|
894
1038
|
}
|
|
895
1039
|
}
|
|
896
1040
|
|