@vib3code/sdk 2.0.3-canary.3b3ca18 → 2.0.3-canary.4874bcf

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.
Files changed (69) hide show
  1. package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +2 -0
  2. package/DOCS/ANDROID_DEPLOYMENT.md +59 -0
  3. package/DOCS/ARCHITECTURE.md +1 -0
  4. package/DOCS/CI_TESTING.md +2 -0
  5. package/DOCS/CLI_ONBOARDING.md +2 -0
  6. package/DOCS/CONTROL_REFERENCE.md +2 -0
  7. package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +2 -0
  8. package/DOCS/ENV_SETUP.md +2 -0
  9. package/DOCS/EPIC_SCROLL_EVENTS.md +2 -0
  10. package/DOCS/EXPANSION_DESIGN.md +2 -0
  11. package/DOCS/EXPANSION_DESIGN_ULTRA.md +2 -0
  12. package/DOCS/EXPORT_FORMATS.md +2 -0
  13. package/DOCS/GPU_DISPOSAL_GUIDE.md +2 -0
  14. package/DOCS/HANDOFF_LANDING_PAGE.md +2 -0
  15. package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +2 -0
  16. package/DOCS/LICENSING_TIERS.md +2 -0
  17. package/DOCS/MASTER_PLAN_2026-01-31.md +2 -0
  18. package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +3 -1
  19. package/DOCS/OBS_SETUP_GUIDE.md +2 -0
  20. package/DOCS/OPTIMIZATION_PLAN_MATH.md +1 -0
  21. package/DOCS/PRODUCT_STRATEGY.md +2 -0
  22. package/DOCS/PROJECT_SETUP.md +2 -0
  23. package/DOCS/README.md +5 -3
  24. package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +2 -0
  25. package/DOCS/RENDERER_LIFECYCLE.md +2 -0
  26. package/DOCS/REPO_MANIFEST.md +2 -0
  27. package/DOCS/ROADMAP.md +2 -0
  28. package/DOCS/SCROLL_TIMELINE_v3.md +2 -0
  29. package/DOCS/SITE_REFACTOR_PLAN.md +2 -0
  30. package/DOCS/STATUS.md +2 -0
  31. package/DOCS/SYSTEM_INVENTORY.md +2 -0
  32. package/DOCS/TELEMETRY_EXPORTS.md +2 -0
  33. package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +2 -0
  34. package/DOCS/VISUAL_ANALYSIS_FACETAD.md +2 -0
  35. package/DOCS/VISUAL_ANALYSIS_SIMONE.md +2 -0
  36. package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +2 -0
  37. package/DOCS/WEBGPU_STATUS.md +2 -0
  38. package/DOCS/XR_BENCHMARKS.md +2 -0
  39. package/DOCS/archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +1 -34
  40. package/DOCS/archive/DEV_TRACK_ANALYSIS.md +1 -80
  41. package/DOCS/archive/DEV_TRACK_PLAN_2026-01-07.md +1 -42
  42. package/DOCS/archive/SESSION_014_PLAN.md +1 -195
  43. package/DOCS/archive/SESSION_LOG_2026-01-07.md +1 -56
  44. package/DOCS/archive/STRATEGIC_BLUEPRINT_2026-01-07.md +1 -72
  45. package/DOCS/archive/SYSTEM_AUDIT_2026-01-30.md +1 -741
  46. package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +1 -38
  47. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-01-31.md +2 -0
  48. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +2 -0
  49. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +2 -0
  50. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +2 -0
  51. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +2 -0
  52. package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +2 -0
  53. package/DOCS/dev-tracks/README.md +2 -0
  54. package/package.json +2 -4
  55. package/src/cli/index.js +59 -5
  56. package/src/export/SVGExporter.js +9 -5
  57. package/src/features/CollectionManager.js +27 -9
  58. package/src/gallery/CollectionManager.js +27 -9
  59. package/src/geometry/warp/HypersphereCore.js +53 -24
  60. package/src/math/Mat4x4.js +272 -128
  61. package/src/math/Projection.js +57 -7
  62. package/src/math/Rotor4D.js +64 -28
  63. package/src/math/Vec4.js +65 -8
  64. package/src/quantum/QuantumVisualizer.js +28 -0
  65. package/src/scene/Node4D.js +74 -24
  66. package/src/testing/ProjectionClass.test.js +38 -0
  67. package/src/variations/VariationManager.js +6 -1
  68. package/src/wasm/WasmLoader.js +11 -6
  69. package/tools/update_projection.py +109 -0
@@ -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(new Float32Array(16));
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
- return new Mat4x4([
359
- m[0], m[4], m[8], m[12],
360
- m[1], m[5], m[9], m[13],
361
- m[2], m[6], m[10], m[14],
362
- m[3], m[7], m[11], m[15]
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 inv = new Float32Array(16);
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
- inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] +
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[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] -
424
- m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
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[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] +
427
- m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
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[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] -
430
- m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
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[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] -
433
- m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
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[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] +
436
- m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
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[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] -
439
- m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
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[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] +
442
- m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
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[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] +
445
- m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6];
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[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] -
448
- m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6];
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[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] +
451
- m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5];
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[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] -
454
- m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5];
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[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] -
457
- m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6];
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[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] +
460
- m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6];
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[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] -
463
- m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5];
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[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] +
466
- m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5];
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
- const det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
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 new Mat4x4(inv);
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
- return new Mat4x4([
693
- c, s, 0, 0,
694
- -s, c, 0, 0,
695
- 0, 0, 1, 0,
696
- 0, 0, 0, 1
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
- return new Mat4x4([
709
- c, 0, -s, 0,
710
- 0, 1, 0, 0,
711
- s, 0, c, 0,
712
- 0, 0, 0, 1
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
- return new Mat4x4([
725
- 1, 0, 0, 0,
726
- 0, c, s, 0,
727
- 0, -s, c, 0,
728
- 0, 0, 0, 1
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
- return new Mat4x4([
742
- c, 0, 0, s,
743
- 0, 1, 0, 0,
744
- 0, 0, 1, 0,
745
- -s, 0, 0, c
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
- return new Mat4x4([
758
- 1, 0, 0, 0,
759
- 0, c, 0, s,
760
- 0, 0, 1, 0,
761
- 0, -s, 0, c
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
- return new Mat4x4([
774
- 1, 0, 0, 0,
775
- 0, 1, 0, 0,
776
- 0, 0, c, s,
777
- 0, 0, -s, c
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
- * @param {object} angles - Rotation angles
805
- * @param {number} [angles.xy=0] - XY plane rotation
806
- * @param {number} [angles.xz=0] - XZ plane rotation
807
- * @param {number} [angles.yz=0] - YZ plane rotation
808
- * @param {number} [angles.xw=0] - XW plane rotation
809
- * @param {number} [angles.yw=0] - YW plane rotation
810
- * @param {number} [angles.zw=0] - ZW plane rotation
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(angles) {
814
- let result = Mat4x4.identity();
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 (angles.xy) result.rotateXY(angles.xy);
817
- if (angles.xz) result.rotateXZ(angles.xz);
818
- if (angles.yz) result.rotateYZ(angles.yz);
819
- if (angles.xw) result.rotateXW(angles.xw);
820
- if (angles.yw) result.rotateYW(angles.yw);
821
- if (angles.zw) result.rotateZW(angles.zw);
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
- return new Mat4x4([
851
- s, 0, 0, 0,
852
- 0, s, 0, 0,
853
- 0, 0, s, 0,
854
- 0, 0, 0, s
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
- return new Mat4x4([
868
- sx, 0, 0, 0,
869
- 0, sy, 0, 0,
870
- 0, 0, sz, 0,
871
- 0, 0, 0, sw
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
- return new Mat4x4([
889
- 1, 0, 0, 0,
890
- 0, 1, 0, 0,
891
- 0, 0, 1, 0,
892
- tx, ty, tz, 1 + tw
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