@vib3code/sdk 2.0.3-canary.45332e3 → 2.0.3-canary.4fbf680

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 (75) 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 +979 -0
  11. package/DOCS/EXPANSION_DESIGN_ULTRA.md +389 -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 +119 -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 +310 -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/experimental/GameLoop.js +72 -0
  57. package/src/experimental/LatticePhysics.js +100 -0
  58. package/src/experimental/LiveDirector.js +143 -0
  59. package/src/experimental/PlayerController4D.js +154 -0
  60. package/src/experimental/VIB3Actor.js +138 -0
  61. package/src/experimental/VIB3Compositor.js +117 -0
  62. package/src/experimental/VIB3Link.js +122 -0
  63. package/src/experimental/VIB3Orchestrator.js +146 -0
  64. package/src/experimental/VIB3Universe.js +109 -0
  65. package/src/experimental/demos/CrystalLabyrinth.js +202 -0
  66. package/src/export/SVGExporter.js +9 -5
  67. package/src/geometry/generators/Crystal.js +2 -2
  68. package/src/geometry/warp/HypersphereCore.js +53 -24
  69. package/src/math/Mat4x4.js +302 -127
  70. package/src/math/Projection.js +57 -7
  71. package/src/math/Rotor4D.js +102 -73
  72. package/src/math/Vec4.js +265 -111
  73. package/src/scene/Node4D.js +74 -24
  74. package/src/testing/ProjectionClass.test.js +38 -0
  75. 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');
@@ -45,12 +53,7 @@ export class Mat4x4 {
45
53
  * @returns {Mat4x4}
46
54
  */
47
55
  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
- ]);
56
+ return new Mat4x4();
54
57
  }
55
58
 
56
59
  /**
@@ -58,7 +61,7 @@ export class Mat4x4 {
58
61
  * @returns {Mat4x4}
59
62
  */
60
63
  static zero() {
61
- return new Mat4x4(new Float32Array(16));
64
+ return new Mat4x4(Mat4x4.UNINITIALIZED);
62
65
  }
63
66
 
64
67
  /**
@@ -157,10 +160,11 @@ export class Mat4x4 {
157
160
  /**
158
161
  * Multiply two matrices
159
162
  * @param {Mat4x4} m - Right operand
163
+ * @param {Mat4x4} [target=null] - Optional target matrix to store result
160
164
  * @returns {Mat4x4} New matrix = this * m
161
165
  */
162
- multiply(m) {
163
- const out = new Mat4x4();
166
+ multiply(m, target = null) {
167
+ const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
164
168
  const r = out.data;
165
169
  const a = this.data;
166
170
  const b = m.data;
@@ -259,16 +263,22 @@ export class Mat4x4 {
259
263
  /**
260
264
  * Transform a Vec4 by this matrix
261
265
  * @param {Vec4} v
266
+ * @param {Vec4} [target=null] - Optional target vector to store result
262
267
  * @returns {Vec4} Transformed vector
263
268
  */
264
- multiplyVec4(v) {
269
+ multiplyVec4(v, target = null) {
265
270
  const m = this.data;
266
- return new Vec4(
267
- m[0] * v.x + m[4] * v.y + m[8] * v.z + m[12] * v.w,
268
- m[1] * v.x + m[5] * v.y + m[9] * v.z + m[13] * v.w,
269
- m[2] * v.x + m[6] * v.y + m[10] * v.z + m[14] * v.w,
270
- m[3] * v.x + m[7] * v.y + m[11] * v.z + m[15] * v.w
271
- );
271
+ const out = target || new Vec4();
272
+
273
+ // Cache components to support aliasing (target === v)
274
+ const x = v.x, y = v.y, z = v.z, w = v.w;
275
+
276
+ out.x = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
277
+ out.y = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
278
+ out.z = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
279
+ out.w = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
280
+
281
+ return out;
272
282
  }
273
283
 
274
284
  /**
@@ -310,41 +320,57 @@ export class Mat4x4 {
310
320
  /**
311
321
  * Add another matrix
312
322
  * @param {Mat4x4} m
323
+ * @param {Mat4x4} [target=null] - Optional target matrix
313
324
  * @returns {Mat4x4} New matrix
314
325
  */
315
- add(m) {
316
- const result = new Float32Array(16);
326
+ add(m, target = null) {
327
+ const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
328
+ const r = out.data;
329
+ const a = this.data;
330
+ const b = m.data;
331
+
317
332
  for (let i = 0; i < 16; i++) {
318
- result[i] = this.data[i] + m.data[i];
333
+ r[i] = a[i] + b[i];
319
334
  }
320
- return new Mat4x4(result);
335
+ return out;
321
336
  }
322
337
 
323
338
  /**
324
339
  * Multiply by scalar
325
340
  * @param {number} s
341
+ * @param {Mat4x4} [target=null] - Optional target matrix
326
342
  * @returns {Mat4x4} New matrix
327
343
  */
328
- scale(s) {
329
- const result = new Float32Array(16);
344
+ scale(s, target = null) {
345
+ const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
346
+ const r = out.data;
347
+ const a = this.data;
348
+
330
349
  for (let i = 0; i < 16; i++) {
331
- result[i] = this.data[i] * s;
350
+ r[i] = a[i] * s;
332
351
  }
333
- return new Mat4x4(result);
352
+ return out;
334
353
  }
335
354
 
336
355
  /**
337
356
  * Transpose matrix
357
+ * @param {Mat4x4} [target=null] - Optional target matrix
338
358
  * @returns {Mat4x4} New transposed matrix
339
359
  */
340
- transpose() {
360
+ transpose(target = null) {
341
361
  const m = this.data;
342
- return new Mat4x4([
343
- m[0], m[4], m[8], m[12],
344
- m[1], m[5], m[9], m[13],
345
- m[2], m[6], m[10], m[14],
346
- m[3], m[7], m[11], m[15]
347
- ]);
362
+ const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
363
+ const r = out.data;
364
+ // If target is same as source, use intermediate or careful swap
365
+ if (target === this) {
366
+ return this.transposeInPlace();
367
+ }
368
+
369
+ r[0] = m[0]; r[4] = m[1]; r[8] = m[2]; r[12] = m[3];
370
+ r[1] = m[4]; r[5] = m[5]; r[9] = m[6]; r[13] = m[7];
371
+ r[2] = m[8]; r[6] = m[9]; r[10] = m[10]; r[14] = m[11];
372
+ r[3] = m[12]; r[7] = m[13]; r[11] = m[14]; r[15] = m[15];
373
+ return out;
348
374
  }
349
375
 
350
376
  /**
@@ -395,61 +421,85 @@ export class Mat4x4 {
395
421
 
396
422
  /**
397
423
  * Calculate inverse matrix
424
+ * @param {Mat4x4} [target=null] - Optional target matrix
398
425
  * @returns {Mat4x4|null} Inverse matrix or null if singular
399
426
  */
400
- inverse() {
427
+ inverse(target = null) {
401
428
  const m = this.data;
402
- const inv = new Float32Array(16);
429
+ const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
430
+ const inv = out.data;
431
+
432
+ // Note: For in-place inversion (target === this), we need to be careful.
433
+ // The standard algorithm uses input values for every output cell.
434
+ // We can check for aliasing or use local variables if we wanted full safety,
435
+ // but simplest is to compute to temp if aliased, or just computing to the array directly works
436
+ // IF we cache everything first. But here we are writing to `inv` index by index.
437
+ // If inv === m, writing inv[0] destroys m[0] which is needed for inv[5] etc.
438
+ // So aliasing is NOT safe with this direct write approach.
439
+
440
+ // Handle aliasing by cloning first if needed, or using temp array.
441
+ // Since we want performance, let's detect aliasing.
442
+ let sourceData = m;
443
+ if (target === this) {
444
+ // Copy source data to temp array so we can write to 'this.data' safely
445
+ // We can't avoid allocation entirely in this specific edge case easily without unrolling everything into locals,
446
+ // which is huge for 4x4 inverse.
447
+ // Using a static temp buffer would be unsafe for threading/recursion (not an issue in JS single thread usually but still).
448
+ // Let's just clone the source data for the calculation.
449
+ sourceData = new Float32Array(m);
450
+ }
451
+
452
+ const s = sourceData;
403
453
 
404
- inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] +
405
- m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
454
+ inv[0] = s[5] * s[10] * s[15] - s[5] * s[11] * s[14] - s[9] * s[6] * s[15] +
455
+ s[9] * s[7] * s[14] + s[13] * s[6] * s[11] - s[13] * s[7] * s[10];
406
456
 
407
- inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] -
408
- m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
457
+ inv[4] = -s[4] * s[10] * s[15] + s[4] * s[11] * s[14] + s[8] * s[6] * s[15] -
458
+ s[8] * s[7] * s[14] - s[12] * s[6] * s[11] + s[12] * s[7] * s[10];
409
459
 
410
- inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] +
411
- m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
460
+ inv[8] = s[4] * s[9] * s[15] - s[4] * s[11] * s[13] - s[8] * s[5] * s[15] +
461
+ s[8] * s[7] * s[13] + s[12] * s[5] * s[11] - s[12] * s[7] * s[9];
412
462
 
413
- inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] -
414
- m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
463
+ inv[12] = -s[4] * s[9] * s[14] + s[4] * s[10] * s[13] + s[8] * s[5] * s[14] -
464
+ s[8] * s[6] * s[13] - s[12] * s[5] * s[10] + s[12] * s[6] * s[9];
415
465
 
416
- inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] -
417
- m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
466
+ inv[1] = -s[1] * s[10] * s[15] + s[1] * s[11] * s[14] + s[9] * s[2] * s[15] -
467
+ s[9] * s[3] * s[14] - s[13] * s[2] * s[11] + s[13] * s[3] * s[10];
418
468
 
419
- inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] +
420
- m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
469
+ inv[5] = s[0] * s[10] * s[15] - s[0] * s[11] * s[14] - s[8] * s[2] * s[15] +
470
+ s[8] * s[3] * s[14] + s[12] * s[2] * s[11] - s[12] * s[3] * s[10];
421
471
 
422
- inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] -
423
- m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
472
+ inv[9] = -s[0] * s[9] * s[15] + s[0] * s[11] * s[13] + s[8] * s[1] * s[15] -
473
+ s[8] * s[3] * s[13] - s[12] * s[1] * s[11] + s[12] * s[3] * s[9];
424
474
 
425
- inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] +
426
- m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
475
+ inv[13] = s[0] * s[9] * s[14] - s[0] * s[10] * s[13] - s[8] * s[1] * s[14] +
476
+ s[8] * s[2] * s[13] + s[12] * s[1] * s[10] - s[12] * s[2] * s[9];
427
477
 
428
- inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] +
429
- m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6];
478
+ inv[2] = s[1] * s[6] * s[15] - s[1] * s[7] * s[14] - s[5] * s[2] * s[15] +
479
+ s[5] * s[3] * s[14] + s[13] * s[2] * s[7] - s[13] * s[3] * s[6];
430
480
 
431
- inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] -
432
- m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6];
481
+ inv[6] = -s[0] * s[6] * s[15] + s[0] * s[7] * s[14] + s[4] * s[2] * s[15] -
482
+ s[4] * s[3] * s[14] - s[12] * s[2] * s[7] + s[12] * s[3] * s[6];
433
483
 
434
- inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] +
435
- m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5];
484
+ inv[10] = s[0] * s[5] * s[15] - s[0] * s[7] * s[13] - s[4] * s[1] * s[15] +
485
+ s[4] * s[3] * s[13] + s[12] * s[1] * s[7] - s[12] * s[3] * s[5];
436
486
 
437
- inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] -
438
- m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5];
487
+ inv[14] = -s[0] * s[5] * s[14] + s[0] * s[6] * s[13] + s[4] * s[1] * s[14] -
488
+ s[4] * s[2] * s[13] - s[12] * s[1] * s[6] + s[12] * s[2] * s[5];
439
489
 
440
- inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] -
441
- m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6];
490
+ inv[3] = -s[1] * s[6] * s[11] + s[1] * s[7] * s[10] + s[5] * s[2] * s[11] -
491
+ s[5] * s[3] * s[10] - s[9] * s[2] * s[7] + s[9] * s[3] * s[6];
442
492
 
443
- inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] +
444
- m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6];
493
+ inv[7] = s[0] * s[6] * s[11] - s[0] * s[7] * s[10] - s[4] * s[2] * s[11] +
494
+ s[4] * s[3] * s[10] + s[8] * s[2] * s[7] - s[8] * s[3] * s[6];
445
495
 
446
- inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] -
447
- m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5];
496
+ inv[11] = -s[0] * s[5] * s[11] + s[0] * s[7] * s[9] + s[4] * s[1] * s[11] -
497
+ s[4] * s[3] * s[9] - s[8] * s[1] * s[7] + s[8] * s[3] * s[5];
448
498
 
449
- inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] +
450
- m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5];
499
+ inv[15] = s[0] * s[5] * s[10] - s[0] * s[6] * s[9] - s[4] * s[1] * s[10] +
500
+ s[4] * s[2] * s[9] + s[8] * s[1] * s[6] - s[8] * s[2] * s[5];
451
501
 
452
- const det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
502
+ const det = s[0] * inv[0] + s[1] * inv[4] + s[2] * inv[8] + s[3] * inv[12];
453
503
 
454
504
  if (Math.abs(det) < 1e-10) {
455
505
  return null; // Singular matrix
@@ -460,7 +510,7 @@ export class Mat4x4 {
460
510
  inv[i] *= invDet;
461
511
  }
462
512
 
463
- return new Mat4x4(inv);
513
+ return out;
464
514
  }
465
515
 
466
516
  /**
@@ -547,6 +597,122 @@ export class Mat4x4 {
547
597
  return new Mat4x4(json.data);
548
598
  }
549
599
 
600
+ // ========== IN-PLACE ROTATIONS ==========
601
+
602
+ /**
603
+ * Rotate in XY plane in place
604
+ * @param {number} angle
605
+ * @returns {Mat4x4} this
606
+ */
607
+ rotateXY(angle) {
608
+ const c = Math.cos(angle);
609
+ const s = Math.sin(angle);
610
+ const m = this.data;
611
+
612
+ for (let i = 0; i < 4; i++) {
613
+ const a0 = m[i]; // Col 0
614
+ const a1 = m[i + 4]; // Col 1
615
+ m[i] = a0 * c + a1 * s;
616
+ m[i + 4] = -a0 * s + a1 * c;
617
+ }
618
+ return this;
619
+ }
620
+
621
+ /**
622
+ * Rotate in XZ plane in place
623
+ * @param {number} angle
624
+ * @returns {Mat4x4} this
625
+ */
626
+ rotateXZ(angle) {
627
+ const c = Math.cos(angle);
628
+ const s = Math.sin(angle);
629
+ const m = this.data;
630
+
631
+ for (let i = 0; i < 4; i++) {
632
+ const a0 = m[i]; // Col 0
633
+ const a2 = m[i + 8]; // Col 2
634
+ m[i] = a0 * c - a2 * s;
635
+ m[i + 8] = a0 * s + a2 * c;
636
+ }
637
+ return this;
638
+ }
639
+
640
+ /**
641
+ * Rotate in YZ plane in place
642
+ * @param {number} angle
643
+ * @returns {Mat4x4} this
644
+ */
645
+ rotateYZ(angle) {
646
+ const c = Math.cos(angle);
647
+ const s = Math.sin(angle);
648
+ const m = this.data;
649
+
650
+ for (let i = 0; i < 4; i++) {
651
+ const a1 = m[i + 4]; // Col 1
652
+ const a2 = m[i + 8]; // Col 2
653
+ m[i + 4] = a1 * c + a2 * s;
654
+ m[i + 8] = -a1 * s + a2 * c;
655
+ }
656
+ return this;
657
+ }
658
+
659
+ /**
660
+ * Rotate in XW plane in place
661
+ * @param {number} angle
662
+ * @returns {Mat4x4} this
663
+ */
664
+ rotateXW(angle) {
665
+ const c = Math.cos(angle);
666
+ const s = Math.sin(angle);
667
+ const m = this.data;
668
+
669
+ for (let i = 0; i < 4; i++) {
670
+ const a0 = m[i]; // Col 0
671
+ const a3 = m[i + 12]; // Col 3
672
+ m[i] = a0 * c + a3 * s;
673
+ m[i + 12] = -a0 * s + a3 * c;
674
+ }
675
+ return this;
676
+ }
677
+
678
+ /**
679
+ * Rotate in YW plane in place
680
+ * @param {number} angle
681
+ * @returns {Mat4x4} this
682
+ */
683
+ rotateYW(angle) {
684
+ const c = Math.cos(angle);
685
+ const s = Math.sin(angle);
686
+ const m = this.data;
687
+
688
+ for (let i = 0; i < 4; i++) {
689
+ const a1 = m[i + 4]; // Col 1
690
+ const a3 = m[i + 12]; // Col 3
691
+ m[i + 4] = a1 * c + a3 * s;
692
+ m[i + 12] = -a1 * s + a3 * c;
693
+ }
694
+ return this;
695
+ }
696
+
697
+ /**
698
+ * Rotate in ZW plane in place
699
+ * @param {number} angle
700
+ * @returns {Mat4x4} this
701
+ */
702
+ rotateZW(angle) {
703
+ const c = Math.cos(angle);
704
+ const s = Math.sin(angle);
705
+ const m = this.data;
706
+
707
+ for (let i = 0; i < 4; i++) {
708
+ const a2 = m[i + 8]; // Col 2
709
+ const a3 = m[i + 12]; // Col 3
710
+ m[i + 8] = a2 * c + a3 * s;
711
+ m[i + 12] = -a2 * s + a3 * c;
712
+ }
713
+ return this;
714
+ }
715
+
550
716
  // ========== ROTATION MATRICES FOR ALL 6 PLANES ==========
551
717
 
552
718
  /**
@@ -557,12 +723,13 @@ export class Mat4x4 {
557
723
  static rotationXY(angle) {
558
724
  const c = Math.cos(angle);
559
725
  const s = Math.sin(angle);
560
- return new Mat4x4([
561
- c, s, 0, 0,
562
- -s, c, 0, 0,
563
- 0, 0, 1, 0,
564
- 0, 0, 0, 1
565
- ]);
726
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
727
+ const r = out.data;
728
+ r[0] = c; r[1] = s;
729
+ r[4] = -s; r[5] = c;
730
+ r[10] = 1;
731
+ r[15] = 1;
732
+ return out;
566
733
  }
567
734
 
568
735
  /**
@@ -573,12 +740,13 @@ export class Mat4x4 {
573
740
  static rotationXZ(angle) {
574
741
  const c = Math.cos(angle);
575
742
  const s = Math.sin(angle);
576
- return new Mat4x4([
577
- c, 0, -s, 0,
578
- 0, 1, 0, 0,
579
- s, 0, c, 0,
580
- 0, 0, 0, 1
581
- ]);
743
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
744
+ const r = out.data;
745
+ r[0] = c; r[2] = -s;
746
+ r[5] = 1;
747
+ r[8] = s; r[10] = c;
748
+ r[15] = 1;
749
+ return out;
582
750
  }
583
751
 
584
752
  /**
@@ -589,12 +757,13 @@ export class Mat4x4 {
589
757
  static rotationYZ(angle) {
590
758
  const c = Math.cos(angle);
591
759
  const s = Math.sin(angle);
592
- return new Mat4x4([
593
- 1, 0, 0, 0,
594
- 0, c, s, 0,
595
- 0, -s, c, 0,
596
- 0, 0, 0, 1
597
- ]);
760
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
761
+ const r = out.data;
762
+ r[0] = 1;
763
+ r[5] = c; r[6] = s;
764
+ r[9] = -s; r[10] = c;
765
+ r[15] = 1;
766
+ return out;
598
767
  }
599
768
 
600
769
  /**
@@ -606,12 +775,13 @@ export class Mat4x4 {
606
775
  static rotationXW(angle) {
607
776
  const c = Math.cos(angle);
608
777
  const s = Math.sin(angle);
609
- return new Mat4x4([
610
- c, 0, 0, s,
611
- 0, 1, 0, 0,
612
- 0, 0, 1, 0,
613
- -s, 0, 0, c
614
- ]);
778
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
779
+ const r = out.data;
780
+ r[0] = c; r[3] = s;
781
+ r[5] = 1;
782
+ r[10] = 1;
783
+ r[12] = -s; r[15] = c;
784
+ return out;
615
785
  }
616
786
 
617
787
  /**
@@ -622,12 +792,13 @@ export class Mat4x4 {
622
792
  static rotationYW(angle) {
623
793
  const c = Math.cos(angle);
624
794
  const s = Math.sin(angle);
625
- return new Mat4x4([
626
- 1, 0, 0, 0,
627
- 0, c, 0, s,
628
- 0, 0, 1, 0,
629
- 0, -s, 0, c
630
- ]);
795
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
796
+ const r = out.data;
797
+ r[0] = 1;
798
+ r[5] = c; r[7] = s;
799
+ r[10] = 1;
800
+ r[13] = -s; r[15] = c;
801
+ return out;
631
802
  }
632
803
 
633
804
  /**
@@ -638,12 +809,13 @@ export class Mat4x4 {
638
809
  static rotationZW(angle) {
639
810
  const c = Math.cos(angle);
640
811
  const s = Math.sin(angle);
641
- return new Mat4x4([
642
- 1, 0, 0, 0,
643
- 0, 1, 0, 0,
644
- 0, 0, c, s,
645
- 0, 0, -s, c
646
- ]);
812
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
813
+ const r = out.data;
814
+ r[0] = 1;
815
+ r[5] = 1;
816
+ r[10] = c; r[11] = s;
817
+ r[14] = -s; r[15] = c;
818
+ return out;
647
819
  }
648
820
 
649
821
  /**
@@ -681,12 +853,12 @@ export class Mat4x4 {
681
853
  static rotationFromAngles(angles) {
682
854
  let result = Mat4x4.identity();
683
855
 
684
- if (angles.xy) result = result.multiply(Mat4x4.rotationXY(angles.xy));
685
- if (angles.xz) result = result.multiply(Mat4x4.rotationXZ(angles.xz));
686
- if (angles.yz) result = result.multiply(Mat4x4.rotationYZ(angles.yz));
687
- if (angles.xw) result = result.multiply(Mat4x4.rotationXW(angles.xw));
688
- if (angles.yw) result = result.multiply(Mat4x4.rotationYW(angles.yw));
689
- if (angles.zw) result = result.multiply(Mat4x4.rotationZW(angles.zw));
856
+ if (angles.xy) result.rotateXY(angles.xy);
857
+ if (angles.xz) result.rotateXZ(angles.xz);
858
+ if (angles.yz) result.rotateYZ(angles.yz);
859
+ if (angles.xw) result.rotateXW(angles.xw);
860
+ if (angles.yw) result.rotateYW(angles.yw);
861
+ if (angles.zw) result.rotateZW(angles.zw);
690
862
 
691
863
  return result;
692
864
  }
@@ -715,12 +887,13 @@ export class Mat4x4 {
715
887
  * @returns {Mat4x4}
716
888
  */
717
889
  static uniformScale(s) {
718
- return new Mat4x4([
719
- s, 0, 0, 0,
720
- 0, s, 0, 0,
721
- 0, 0, s, 0,
722
- 0, 0, 0, s
723
- ]);
890
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
891
+ const r = out.data;
892
+ r[0] = s;
893
+ r[5] = s;
894
+ r[10] = s;
895
+ r[15] = s;
896
+ return out;
724
897
  }
725
898
 
726
899
  /**
@@ -732,12 +905,13 @@ export class Mat4x4 {
732
905
  * @returns {Mat4x4}
733
906
  */
734
907
  static scale(sx, sy, sz, sw = 1) {
735
- return new Mat4x4([
736
- sx, 0, 0, 0,
737
- 0, sy, 0, 0,
738
- 0, 0, sz, 0,
739
- 0, 0, 0, sw
740
- ]);
908
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
909
+ const r = out.data;
910
+ r[0] = sx;
911
+ r[5] = sy;
912
+ r[10] = sz;
913
+ r[15] = sw;
914
+ return out;
741
915
  }
742
916
 
743
917
  /**
@@ -753,12 +927,13 @@ export class Mat4x4 {
753
927
  static translation(tx, ty, tz, tw = 0) {
754
928
  // For true 4D translation, you need 5D homogeneous coordinates
755
929
  // This is a placeholder that adds the translation to the W column
756
- return new Mat4x4([
757
- 1, 0, 0, 0,
758
- 0, 1, 0, 0,
759
- 0, 0, 1, 0,
760
- tx, ty, tz, 1 + tw
761
- ]);
930
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
931
+ const r = out.data;
932
+ r[0] = 1;
933
+ r[5] = 1;
934
+ r[10] = 1;
935
+ r[12] = tx; r[13] = ty; r[14] = tz; r[15] = 1 + tw;
936
+ return out;
762
937
  }
763
938
  }
764
939