@vib3code/sdk 2.0.3-canary.45332e3 → 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 (80) 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/features/CollectionManager.js +27 -9
  68. package/src/gallery/CollectionManager.js +27 -9
  69. package/src/geometry/generators/Crystal.js +2 -2
  70. package/src/geometry/warp/HypersphereCore.js +53 -24
  71. package/src/math/Mat4x4.js +418 -142
  72. package/src/math/Projection.js +57 -7
  73. package/src/math/Rotor4D.js +102 -73
  74. package/src/math/Vec4.js +265 -111
  75. package/src/quantum/QuantumVisualizer.js +28 -0
  76. package/src/scene/Node4D.js +74 -24
  77. package/src/testing/ProjectionClass.test.js +38 -0
  78. package/src/variations/VariationManager.js +6 -1
  79. package/src/wasm/WasmLoader.js +11 -6
  80. package/tools/update_projection.py +109 -0
@@ -500,29 +500,74 @@ export class Node4D {
500
500
  * @private
501
501
  */
502
502
  _updateLocalMatrix() {
503
- // Start with identity
504
- this._localMatrix = Mat4x4.identity();
503
+ // Ensure matrix exists
504
+ if (!this._localMatrix) {
505
+ this._localMatrix = new Mat4x4();
506
+ }
507
+
508
+ const m = this._localMatrix.data;
509
+ const s = this._scale;
510
+ const p = this._position;
511
+
512
+ // 1. Write rotation directly to local matrix (No allocation)
513
+ this._rotation.toMatrix(m);
514
+
515
+ // 2. Apply scale (Diagonal matrix multiplication on the right)
516
+ // M = M * S
517
+ // Columns of M are scaled by s.x, s.y, s.z, s.w
518
+
519
+ // Col 0
520
+ m[0] *= s.x; m[1] *= s.x; m[2] *= s.x; m[3] *= s.x;
521
+ // Col 1
522
+ m[4] *= s.y; m[5] *= s.y; m[6] *= s.y; m[7] *= s.y;
523
+ // Col 2
524
+ m[8] *= s.z; m[9] *= s.z; m[10] *= s.z; m[11] *= s.z;
525
+ // Col 3
526
+ m[12] *= s.w; m[13] *= s.w; m[14] *= s.w; m[15] *= s.w;
527
+
528
+ // 3. Apply translation (Matrix multiplication on the left)
529
+ // M = T * M
530
+ // T is standard 3D translation:
531
+ // [ 1 0 0 px ]
532
+ // [ 0 1 0 py ]
533
+ // [ 0 0 1 pz ]
534
+ // [ 0 0 0 1 ]
535
+ //
536
+ // Row 0 += px * Row 3
537
+ // Row 1 += py * Row 3
538
+ // Row 2 += pz * Row 3
539
+
540
+ const px = p.x;
541
+ const py = p.y;
542
+ const pz = p.z;
543
+
544
+ // Row 3 elements of M (which are used in the calculation)
545
+ const m3 = m[3];
546
+ const m7 = m[7];
547
+ const m11 = m[11];
548
+ const m15 = m[15];
549
+
550
+ if (px !== 0) {
551
+ m[0] += px * m3;
552
+ m[4] += px * m7;
553
+ m[8] += px * m11;
554
+ m[12] += px * m15;
555
+ }
556
+
557
+ if (py !== 0) {
558
+ m[1] += py * m3;
559
+ m[5] += py * m7;
560
+ m[9] += py * m11;
561
+ m[13] += py * m15;
562
+ }
563
+
564
+ if (pz !== 0) {
565
+ m[2] += pz * m3;
566
+ m[6] += pz * m7;
567
+ m[10] += pz * m11;
568
+ m[14] += pz * m15;
569
+ }
505
570
 
506
- // Apply scale
507
- const scaleMatrix = Mat4x4.identity();
508
- scaleMatrix.set(0, 0, this._scale.x);
509
- scaleMatrix.set(1, 1, this._scale.y);
510
- scaleMatrix.set(2, 2, this._scale.z);
511
- scaleMatrix.set(3, 3, this._scale.w);
512
-
513
- // Apply rotation (toMatrix returns Float32Array, wrap in Mat4x4)
514
- const rotationMatrix = new Mat4x4(this._rotation.toMatrix());
515
-
516
- // Apply translation (in 4D, translation is stored in last column, keep [3,3]=1)
517
- const translationMatrix = Mat4x4.identity();
518
- translationMatrix.set(0, 3, this._position.x);
519
- translationMatrix.set(1, 3, this._position.y);
520
- translationMatrix.set(2, 3, this._position.z);
521
- // Note: position.w is the 4th spatial coordinate, handled separately
522
- // Matrix[3,3] must remain 1 for proper transformation
523
-
524
- // Compose: T * R * S
525
- this._localMatrix = translationMatrix.multiply(rotationMatrix).multiply(scaleMatrix);
526
571
  this._localDirty = false;
527
572
  }
528
573
 
@@ -535,10 +580,15 @@ export class Node4D {
535
580
  this._updateLocalMatrix();
536
581
  }
537
582
 
583
+ // Ensure matrix exists
584
+ if (!this._worldMatrix) {
585
+ this._worldMatrix = new Mat4x4();
586
+ }
587
+
538
588
  if (this._parent) {
539
- this._worldMatrix = this._parent.worldMatrix.multiply(this._localMatrix);
589
+ this._parent.worldMatrix.multiply(this._localMatrix, this._worldMatrix);
540
590
  } else {
541
- this._worldMatrix = this._localMatrix.clone();
591
+ this._worldMatrix.copy(this._localMatrix);
542
592
  }
543
593
 
544
594
  this._worldDirty = false;
@@ -0,0 +1,38 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import Projection from '../math/Projection.js';
3
+ import Vec4 from '../math/Vec4.js';
4
+
5
+ describe('Projection Class', () => {
6
+ it('should project using perspective', () => {
7
+ const v = new Vec4(1, 1, 1, 0);
8
+ const p = Projection.perspective(v, 2);
9
+ expect(p.x).toBeCloseTo(0.5);
10
+ expect(p.y).toBeCloseTo(0.5);
11
+ expect(p.z).toBeCloseTo(0.5);
12
+ expect(p.w).toBe(0);
13
+ });
14
+
15
+ it('should support target vector in perspective', () => {
16
+ const v = new Vec4(1, 1, 1, 0);
17
+ const target = new Vec4();
18
+ const result = Projection.perspective(v, 2, {}, target);
19
+ expect(result).toBe(target);
20
+ expect(target.x).toBeCloseTo(0.5);
21
+ });
22
+
23
+ it('should project array using perspectiveArray', () => {
24
+ const vectors = [new Vec4(1, 1, 1, 0), new Vec4(2, 2, 2, 0)];
25
+ const result = Projection.perspectiveArray(vectors, 2);
26
+ expect(result.length).toBe(2);
27
+ expect(result[0].x).toBeCloseTo(0.5);
28
+ expect(result[1].x).toBeCloseTo(1.0);
29
+ });
30
+
31
+ it('should reuse target array in perspectiveArray', () => {
32
+ const vectors = [new Vec4(1, 1, 1, 0)];
33
+ const targetArray = [new Vec4()];
34
+ const result = Projection.perspectiveArray(vectors, 2, {}, targetArray);
35
+ expect(result).toBe(targetArray);
36
+ expect(targetArray[0].x).toBeCloseTo(0.5);
37
+ });
38
+ });
@@ -417,7 +417,12 @@ export class VariationManager {
417
417
  * Get variation statistics
418
418
  */
419
419
  getStatistics() {
420
- const customCount = this.customVariations.filter(v => v !== null).length;
420
+ let customCount = 0;
421
+ for (let i = 0; i < this.customVariations.length; i++) {
422
+ if (this.customVariations[i] !== null) {
423
+ customCount++;
424
+ }
425
+ }
421
426
 
422
427
  return {
423
428
  totalVariations: this.totalVariations,
@@ -200,12 +200,17 @@ function createFallbackModule() {
200
200
  ),
201
201
 
202
202
  // Projections
203
- projectPerspective: JsProjection.perspectiveProject,
204
- projectStereographic: JsProjection.stereographicProject,
205
- projectOrthographic: JsProjection.orthographicProject,
206
- projectOblique: JsProjection.obliqueProject,
207
- projectSlice: JsProjection.sliceProject,
208
- projectToFloatArray: JsProjection.projectToFloatArray
203
+ projectPerspective: JsProjection.Projection.perspective,
204
+ projectStereographic: JsProjection.Projection.stereographic,
205
+ projectOrthographic: JsProjection.Projection.orthographic,
206
+ projectOblique: JsProjection.Projection.oblique,
207
+ projectSlice: (v, wPlane, tolerance) => {
208
+ if (JsProjection.SliceProjection.isInSlice(v, wPlane, tolerance)) {
209
+ return JsProjection.Projection.orthographic(v);
210
+ }
211
+ return null;
212
+ },
213
+ projectToFloatArray: JsProjection.Projection.perspectivePacked
209
214
  };
210
215
  }
211
216
 
@@ -0,0 +1,109 @@
1
+ import re
2
+
3
+ file_path = 'src/math/Projection.js'
4
+
5
+ with open(file_path, 'r') as f:
6
+ content = f.read()
7
+
8
+ # Replace perspective JSDoc and Implementation
9
+ perspective_old = r""" * @param {Vec4} v - 4D point
10
+ * @param {number} d - Distance parameter (typically 1.5-5)
11
+ * @returns {Vec4} Projected point (w=0)
12
+ */
13
+ static perspective(v, d = 2, options = {}) {
14
+ if (typeof d === 'object') {
15
+ options = d;
16
+ d = options.d ?? 2;
17
+ }
18
+ const epsilon = options.epsilon ?? DEFAULT_EPSILON;
19
+ const denom = clampDenominator(d - v.w, epsilon);
20
+ const scale = 1 / denom;
21
+ return new Vec4(v.x * scale, v.y * scale, v.z * scale, 0);
22
+ }"""
23
+
24
+ perspective_new = r""" * @param {Vec4} v - 4D point
25
+ * @param {number} d - Distance parameter (typically 1.5-5)
26
+ * @param {object} [options] - Projection options
27
+ * @param {Vec4} [target] - Optional target vector to write result to
28
+ * @returns {Vec4} Projected point (w=0)
29
+ */
30
+ static perspective(v, d = 2, options = {}, target = null) {
31
+ if (typeof d === 'object') {
32
+ options = d;
33
+ d = options.d ?? 2;
34
+ }
35
+
36
+ // Handle options overload or direct target argument
37
+ if (!target && options && options.target) {
38
+ target = options.target;
39
+ }
40
+
41
+ const epsilon = (options && options.epsilon) ?? DEFAULT_EPSILON;
42
+ const denom = clampDenominator(d - v.w, epsilon);
43
+ const scale = 1 / denom;
44
+
45
+ if (target) {
46
+ return target.set(v.x * scale, v.y * scale, v.z * scale, 0);
47
+ }
48
+ return new Vec4(v.x * scale, v.y * scale, v.z * scale, 0);
49
+ }"""
50
+
51
+ if perspective_old in content:
52
+ content = content.replace(perspective_old, perspective_new)
53
+ else:
54
+ print("Could not find perspective implementation to replace.")
55
+ # Attempt more robust search if exact match fails? No, simpler is safer for now.
56
+
57
+ # Replace perspectiveArray JSDoc and Implementation
58
+ perspective_array_old = r""" /**
59
+ * Project array of Vec4s using perspective projection
60
+ * @param {Vec4[]} vectors
61
+ * @param {number} d
62
+ * @returns {Vec4[]}
63
+ */
64
+ static perspectiveArray(vectors, d = 2, options = {}) {
65
+ return vectors.map(v => Projection.perspective(v, d, options));
66
+ }"""
67
+
68
+ perspective_array_new = r""" /**
69
+ * Project array of Vec4s using perspective projection
70
+ * @param {Vec4[]} vectors
71
+ * @param {number} d
72
+ * @param {object} [options]
73
+ * @param {Vec4[]} [target] - Optional target array to write results to
74
+ * @returns {Vec4[]}
75
+ */
76
+ static perspectiveArray(vectors, d = 2, options = {}, target = null) {
77
+ // Handle options overload for 'd'
78
+ if (typeof d === 'object') {
79
+ options = d;
80
+ d = options.d ?? 2;
81
+ }
82
+
83
+ if (!target) {
84
+ return vectors.map(v => Projection.perspective(v, d, options));
85
+ }
86
+
87
+ const count = vectors.length;
88
+ // Iterate and reuse
89
+ for (let i = 0; i < count; i++) {
90
+ const out = target[i];
91
+ if (out) {
92
+ Projection.perspective(vectors[i], d, options, out);
93
+ } else {
94
+ target[i] = Projection.perspective(vectors[i], d, options);
95
+ }
96
+ }
97
+
98
+ return target;
99
+ }"""
100
+
101
+ if perspective_array_old in content:
102
+ content = content.replace(perspective_array_old, perspective_array_new)
103
+ else:
104
+ print("Could not find perspectiveArray implementation to replace.")
105
+
106
+ with open(file_path, 'w') as f:
107
+ f.write(content)
108
+
109
+ print("Updated Projection.js")