@vib3code/sdk 2.0.1 → 2.0.3-canary.6f35b4c

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 (96) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +243 -0
  3. package/DOCS/CLI_ONBOARDING.md +1 -1
  4. package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +117 -0
  5. package/DOCS/EPIC_SCROLL_EVENTS.md +773 -0
  6. package/DOCS/HANDOFF_LANDING_PAGE.md +154 -0
  7. package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +493 -0
  8. package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +937 -0
  9. package/DOCS/PRODUCT_STRATEGY.md +63 -0
  10. package/DOCS/README.md +103 -0
  11. package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +97 -0
  12. package/DOCS/ROADMAP.md +111 -0
  13. package/DOCS/SCROLL_TIMELINE_v3.md +269 -0
  14. package/DOCS/SITE_REFACTOR_PLAN.md +100 -0
  15. package/DOCS/STATUS.md +24 -0
  16. package/DOCS/SYSTEM_INVENTORY.md +33 -30
  17. package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +85 -0
  18. package/DOCS/VISUAL_ANALYSIS_FACETAD.md +133 -0
  19. package/DOCS/VISUAL_ANALYSIS_SIMONE.md +95 -0
  20. package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +86 -0
  21. package/DOCS/{BLUEPRINT_EXECUTION_PLAN_2026-01-07.md → archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md} +1 -1
  22. package/DOCS/{DEV_TRACK_ANALYSIS.md → archive/DEV_TRACK_ANALYSIS.md} +3 -0
  23. package/DOCS/{SYSTEM_AUDIT_2026-01-30.md → archive/SYSTEM_AUDIT_2026-01-30.md} +3 -0
  24. package/DOCS/{DEV_TRACK_SESSION_2026-01-31.md → dev-tracks/DEV_TRACK_SESSION_2026-01-31.md} +1 -1
  25. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +231 -0
  26. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +127 -0
  27. package/DOCS/dev-tracks/README.md +10 -0
  28. package/README.md +26 -13
  29. package/cpp/CMakeLists.txt +236 -0
  30. package/cpp/bindings/embind.cpp +269 -0
  31. package/cpp/build.sh +129 -0
  32. package/cpp/geometry/Crystal.cpp +103 -0
  33. package/cpp/geometry/Fractal.cpp +136 -0
  34. package/cpp/geometry/GeometryGenerator.cpp +262 -0
  35. package/cpp/geometry/KleinBottle.cpp +71 -0
  36. package/cpp/geometry/Sphere.cpp +134 -0
  37. package/cpp/geometry/Tesseract.cpp +94 -0
  38. package/cpp/geometry/Tetrahedron.cpp +83 -0
  39. package/cpp/geometry/Torus.cpp +65 -0
  40. package/cpp/geometry/WarpFunctions.cpp +238 -0
  41. package/cpp/geometry/Wave.cpp +85 -0
  42. package/cpp/include/vib3_ffi.h +238 -0
  43. package/cpp/math/Mat4x4.cpp +409 -0
  44. package/cpp/math/Mat4x4.hpp +209 -0
  45. package/cpp/math/Projection.cpp +142 -0
  46. package/cpp/math/Projection.hpp +148 -0
  47. package/cpp/math/Rotor4D.cpp +322 -0
  48. package/cpp/math/Rotor4D.hpp +204 -0
  49. package/cpp/math/Vec4.cpp +303 -0
  50. package/cpp/math/Vec4.hpp +225 -0
  51. package/cpp/src/vib3_ffi.cpp +607 -0
  52. package/cpp/tests/Geometry_test.cpp +213 -0
  53. package/cpp/tests/Mat4x4_test.cpp +494 -0
  54. package/cpp/tests/Projection_test.cpp +298 -0
  55. package/cpp/tests/Rotor4D_test.cpp +423 -0
  56. package/cpp/tests/Vec4_test.cpp +489 -0
  57. package/package.json +31 -27
  58. package/src/agent/mcp/MCPServer.js +722 -0
  59. package/src/agent/mcp/stdio-server.js +264 -0
  60. package/src/agent/mcp/tools.js +367 -0
  61. package/src/cli/index.js +0 -0
  62. package/src/core/CanvasManager.js +97 -204
  63. package/src/core/ErrorReporter.js +1 -1
  64. package/src/core/Parameters.js +1 -1
  65. package/src/core/VIB3Engine.js +38 -1
  66. package/src/core/VitalitySystem.js +53 -0
  67. package/src/core/renderers/HolographicRendererAdapter.js +2 -2
  68. package/src/creative/AestheticMapper.js +628 -0
  69. package/src/creative/ChoreographyPlayer.js +481 -0
  70. package/src/export/TradingCardManager.js +3 -4
  71. package/src/faceted/FacetedSystem.js +237 -388
  72. package/src/holograms/HolographicVisualizer.js +29 -12
  73. package/src/holograms/RealHolographicSystem.js +68 -12
  74. package/src/polychora/PolychoraSystem.js +77 -0
  75. package/src/quantum/QuantumEngine.js +103 -66
  76. package/src/quantum/QuantumVisualizer.js +7 -2
  77. package/src/render/UnifiedRenderBridge.js +3 -0
  78. package/src/shaders/faceted/faceted.frag.glsl +220 -80
  79. package/src/shaders/faceted/faceted.frag.wgsl +138 -97
  80. package/src/shaders/holographic/holographic.frag.glsl +28 -9
  81. package/src/shaders/holographic/holographic.frag.wgsl +107 -38
  82. package/src/shaders/quantum/quantum.frag.glsl +1 -0
  83. package/src/shaders/quantum/quantum.frag.wgsl +1 -1
  84. package/src/viewer/index.js +1 -1
  85. package/tools/headless-renderer.js +258 -0
  86. package/tools/shader-sync-verify.js +8 -4
  87. package/tools/site-analysis/all-reports.json +32 -0
  88. package/tools/site-analysis/combined-analysis.md +50 -0
  89. package/tools/site-analyzer.mjs +779 -0
  90. package/tools/visual-catalog/capture.js +276 -0
  91. package/tools/visual-catalog/composite.js +138 -0
  92. /package/DOCS/{DEV_TRACK_PLAN_2026-01-07.md → archive/DEV_TRACK_PLAN_2026-01-07.md} +0 -0
  93. /package/DOCS/{SESSION_014_PLAN.md → archive/SESSION_014_PLAN.md} +0 -0
  94. /package/DOCS/{SESSION_LOG_2026-01-07.md → archive/SESSION_LOG_2026-01-07.md} +0 -0
  95. /package/DOCS/{STRATEGIC_BLUEPRINT_2026-01-07.md → archive/STRATEGIC_BLUEPRINT_2026-01-07.md} +0 -0
  96. /package/src/viewer/{ReactivityManager.js → ViewerInputHandler.js} +0 -0
@@ -1,217 +1,110 @@
1
1
  /**
2
- * Dead Simple Canvas Manager - Just hide/show containers + fresh engines
3
- * No canvas destruction - HTML canvases stay put, just switch visibility
2
+ * CanvasManager - Creates and manages 5-layer canvas architecture per system.
3
+ *
4
+ * Provides the API surface expected by VIB3Engine:
5
+ * constructor(containerId)
6
+ * createSystemCanvases(systemName) -> string[]
7
+ * registerContext(canvasId, gl)
8
+ * destroy()
4
9
  */
5
10
 
6
11
  export class CanvasManager {
7
- constructor() {
8
- this.currentSystem = null;
9
- this.currentEngine = null;
10
- }
11
-
12
- async switchToSystem(systemName, engineClasses) {
13
- console.log(`🔄 DESTROY OLD → CREATE NEW: ${systemName}`);
14
-
15
- // STEP 1: DESTROY current engine completely
16
- if (this.currentEngine) {
17
- if (this.currentEngine.setActive) {
18
- this.currentEngine.setActive(false);
19
- }
20
- if (this.currentEngine.destroy) {
21
- this.currentEngine.destroy();
22
- }
23
- console.log('💥 Old engine destroyed');
24
- }
25
-
26
- // STEP 2: DESTROY old WebGL contexts
27
- this.destroyOldWebGLContexts();
28
-
29
- // STEP 3: DESTROY all canvases + CREATE 5 fresh ones
30
- this.destroyAllCanvasesAndCreateFresh(systemName);
31
-
32
- // STEP 4: CREATE fresh engine
33
- const engine = await this.createFreshEngine(systemName, engineClasses);
34
-
35
- // STEP 5: Start new engine
36
- if (engine && engine.setActive) {
37
- engine.setActive(true);
12
+ constructor(containerId = 'vib3-container') {
13
+ this.containerId = containerId;
14
+ this.container = (typeof document !== 'undefined')
15
+ ? document.getElementById(containerId)
16
+ : null;
17
+ this.currentSystem = null;
18
+ this.createdCanvases = [];
19
+ this.registeredContexts = new Map();
38
20
  }
39
-
40
- this.currentSystem = systemName;
41
- this.currentEngine = engine;
42
- console.log(`✅ DESTROY → CREATE complete: ${systemName} ready`);
43
- return engine;
44
- }
45
21
 
46
- destroyOldWebGLContexts() {
47
- console.log('💥 COMPLETE DESTRUCTION: WebGL contexts + old system cleanup...');
48
-
49
- // STEP 1: Kill all WebGL contexts first
50
- const allCanvases = document.querySelectorAll('canvas');
51
- let destroyedCount = 0;
52
-
53
- allCanvases.forEach(canvas => {
54
- // Get any existing WebGL context
55
- const gl = canvas.getContext('webgl2') || canvas.getContext('webgl');
56
- if (gl) {
57
- // Force context loss
58
- const loseContextExt = gl.getExtension('WEBGL_lose_context');
59
- if (loseContextExt) {
60
- loseContextExt.loseContext();
61
- destroyedCount++;
22
+ /**
23
+ * Create 5 canvases with system-appropriate IDs inside the container.
24
+ * Returns the array of canvas IDs created.
25
+ */
26
+ createSystemCanvases(systemName) {
27
+ // Tear down previous canvases
28
+ this._removeCreatedCanvases();
29
+
30
+ const canvasIds = this._getCanvasIdsForSystem(systemName);
31
+
32
+ if (this.container) {
33
+ const viewWidth = this.container.clientWidth || (typeof window !== 'undefined' ? window.innerWidth : 800);
34
+ const viewHeight = this.container.clientHeight || (typeof window !== 'undefined' ? window.innerHeight : 600);
35
+ const dpr = (typeof window !== 'undefined') ? Math.min(window.devicePixelRatio || 1, 2) : 1;
36
+
37
+ canvasIds.forEach((canvasId, index) => {
38
+ const canvas = document.createElement('canvas');
39
+ canvas.id = canvasId;
40
+ canvas.className = 'visualization-canvas';
41
+ canvas.style.position = 'absolute';
42
+ canvas.style.top = '0';
43
+ canvas.style.left = '0';
44
+ canvas.style.width = '100%';
45
+ canvas.style.height = '100%';
46
+ canvas.style.zIndex = String(index + 1);
47
+ canvas.width = viewWidth * dpr;
48
+ canvas.height = viewHeight * dpr;
49
+ this.container.appendChild(canvas);
50
+ this.createdCanvases.push(canvas);
51
+ });
62
52
  }
63
- }
64
- });
65
-
66
- // STEP 2: Clear all global engine references (old system cleanup)
67
- if (window.engine) {
68
- console.log('💥 Clearing window.engine');
69
- window.engine = null;
70
- }
71
- if (window.quantumEngine) {
72
- console.log('💥 Clearing window.quantumEngine');
73
- window.quantumEngine = null;
74
- }
75
- if (window.holographicSystem) {
76
- console.log('💥 Clearing window.holographicSystem');
77
- window.holographicSystem = null;
53
+
54
+ this.currentSystem = systemName;
55
+ return canvasIds;
78
56
  }
79
- if (window.polychoraSystem) {
80
- console.log('💥 Clearing window.polychoraSystem');
81
- window.polychoraSystem = null;
57
+
58
+ /**
59
+ * Track a WebGL context so we can force-lose it during cleanup.
60
+ */
61
+ registerContext(canvasId, gl) {
62
+ this.registeredContexts.set(canvasId, gl);
82
63
  }
83
-
84
- console.log(`💥 DESTRUCTION COMPLETE: ${destroyedCount} WebGL contexts destroyed, all engine refs cleared`);
85
- }
86
64
 
87
- destroyAllCanvasesAndCreateFresh(systemName) {
88
- console.log('💥 DESTROYING ALL CANVASES + CREATING 5 FRESH ONES');
89
-
90
- // STEP 1: DESTROY all existing canvases completely
91
- const allCanvases = document.querySelectorAll('canvas');
92
- allCanvases.forEach(canvas => canvas.remove());
93
- console.log(`💥 Destroyed ${allCanvases.length} old canvases`);
94
-
95
- // STEP 2: Clear all containers
96
- const containers = ['vib34dLayers', 'quantumLayers', 'holographicLayers', 'polychoraLayers'];
97
- containers.forEach(containerId => {
98
- const container = document.getElementById(containerId);
99
- if (container) {
100
- container.innerHTML = '';
101
- container.style.display = 'none';
102
- }
103
- });
104
-
105
- // STEP 3: CREATE 5 fresh canvases for the new system
106
- const targetId = systemName === 'faceted' ? 'vib34dLayers' : `${systemName}Layers`;
107
- const targetContainer = document.getElementById(targetId);
108
-
109
- if (!targetContainer) {
110
- console.error(`❌ Container ${targetId} not found`);
111
- return;
65
+ /**
66
+ * Destroy all managed canvases and force-lose registered WebGL contexts.
67
+ */
68
+ destroy() {
69
+ // Force-lose all tracked contexts
70
+ for (const [, gl] of this.registeredContexts) {
71
+ try {
72
+ const ext = gl.getExtension('WEBGL_lose_context');
73
+ if (ext) ext.loseContext();
74
+ } catch (_) { /* context may already be lost */ }
75
+ }
76
+ this.registeredContexts.clear();
77
+
78
+ this._removeCreatedCanvases();
79
+ this.currentSystem = null;
112
80
  }
113
-
114
- // Create canvas IDs for this system
115
- const canvasIds = this.getCanvasIdsForSystem(systemName);
116
-
117
- // Create 5 fresh canvases
118
- canvasIds.forEach((canvasId, index) => {
119
- const canvas = document.createElement('canvas');
120
- canvas.id = canvasId;
121
- canvas.className = 'visualization-canvas';
122
- canvas.style.position = 'absolute';
123
- canvas.style.top = '0';
124
- canvas.style.left = '0';
125
- canvas.style.width = '100%';
126
- canvas.style.height = '100%';
127
- canvas.style.zIndex = index + 1;
128
-
129
- // Set canvas dimensions
130
- const viewWidth = window.innerWidth;
131
- const viewHeight = window.innerHeight;
132
- const dpr = Math.min(window.devicePixelRatio || 1, 2);
133
- canvas.width = viewWidth * dpr;
134
- canvas.height = viewHeight * dpr;
135
-
136
- targetContainer.appendChild(canvas);
137
- });
138
-
139
- // Show the target container
140
- targetContainer.style.display = 'block';
141
- targetContainer.style.visibility = 'visible';
142
- targetContainer.style.opacity = '1';
143
-
144
- console.log(`✅ Created 5 fresh canvases for ${systemName}: ${canvasIds.join(', ')}`);
145
- }
146
-
147
- getCanvasIdsForSystem(systemName) {
148
- const baseIds = ['background-canvas', 'shadow-canvas', 'content-canvas', 'highlight-canvas', 'accent-canvas'];
149
-
150
- switch (systemName) {
151
- case 'faceted':
152
- return baseIds;
153
- case 'quantum':
154
- return baseIds.map(id => `quantum-${id}`);
155
- case 'holographic':
156
- return baseIds.map(id => `holo-${id}`);
157
- case 'polychora':
158
- return baseIds.map(id => `polychora-${id}`);
159
- default:
160
- return baseIds;
81
+
82
+ // ── Private helpers ──
83
+
84
+ _removeCreatedCanvases() {
85
+ for (const canvas of this.createdCanvases) {
86
+ canvas.remove();
87
+ }
88
+ this.createdCanvases = [];
161
89
  }
162
- }
163
-
164
- async createFreshEngine(systemName, engineClasses) {
165
- console.log(`🚀 Creating fresh ${systemName} engine`);
166
-
167
- let engine = null;
168
-
169
- try {
170
- switch(systemName) {
171
- case 'faceted':
172
- if (engineClasses.VIB34DIntegratedEngine) {
173
- engine = new engineClasses.VIB34DIntegratedEngine();
174
- window.engine = engine;
175
- console.log('✅ Fresh Faceted engine');
176
- }
177
- break;
178
-
179
- case 'quantum':
180
- if (engineClasses.QuantumEngine) {
181
- engine = new engineClasses.QuantumEngine();
182
- window.quantumEngine = engine;
183
- console.log('✅ Fresh Quantum engine');
184
- }
185
- break;
186
-
187
- case 'holographic':
188
- if (engineClasses.RealHolographicSystem) {
189
- engine = new engineClasses.RealHolographicSystem();
190
- window.holographicSystem = engine;
191
- console.log('✅ Fresh Holographic engine');
192
- }
193
- break;
194
-
195
- case 'polychora':
196
- // POLYCHORA: TBD placeholder - not production ready
197
- // Engine disabled until system is complete
198
- console.warn('⚠️ Polychora system is TBD placeholder - not available');
199
- if (false && engineClasses.NewPolychoraEngine) {
200
- engine = new engineClasses.NewPolychoraEngine();
201
- window.newPolychoraEngine = engine;
202
- console.log('✅ Fresh TRUE 4D Polychora Engine with VIB34D DNA');
203
- }
204
- break;
205
-
206
- default:
207
- console.error(`❌ Unknown system: ${systemName}`);
208
- }
209
-
210
- } catch (error) {
211
- console.error(`💥 Engine creation failed for ${systemName}:`, error);
212
- engine = null;
90
+
91
+ _getCanvasIdsForSystem(systemName) {
92
+ const baseIds = [
93
+ 'background-canvas', 'shadow-canvas', 'content-canvas',
94
+ 'highlight-canvas', 'accent-canvas'
95
+ ];
96
+
97
+ switch (systemName) {
98
+ case 'faceted':
99
+ return baseIds;
100
+ case 'quantum':
101
+ return baseIds.map(id => `quantum-${id}`);
102
+ case 'holographic':
103
+ return baseIds.map(id => `holo-${id}`);
104
+ case 'polychora':
105
+ return baseIds.map(id => `polychora-${id}`);
106
+ default:
107
+ return baseIds;
108
+ }
213
109
  }
214
-
215
- return engine;
216
- }
217
- }
110
+ }
@@ -86,7 +86,7 @@ export class ErrorReporter {
86
86
  timestamp: Date.now(),
87
87
  url: typeof location !== 'undefined' ? location.pathname : '',
88
88
  userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',
89
- sdkVersion: '2.0.0',
89
+ sdkVersion: '2.0.3',
90
90
  };
91
91
 
92
92
  // Custom callback takes priority
@@ -272,7 +272,7 @@ export class ParameterManager {
272
272
  exportConfiguration() {
273
273
  return {
274
274
  type: 'vib34d-integrated-config',
275
- version: '1.0.0',
275
+ version: '2.0.3',
276
276
  timestamp: new Date().toISOString(),
277
277
  name: `VIB34D Config ${new Date().toLocaleDateString()}`,
278
278
  parameters: { ...this.params }
@@ -15,6 +15,7 @@ import { RealHolographicSystem } from '../holograms/RealHolographicSystem.js';
15
15
  import { ReactivityManager } from '../reactivity/ReactivityManager.js';
16
16
  import { ReactivityConfig } from '../reactivity/ReactivityConfig.js';
17
17
  import { SpatialInputSystem } from '../reactivity/SpatialInputSystem.js';
18
+ import { VitalitySystem } from './VitalitySystem.js';
18
19
 
19
20
  export class VIB3Engine {
20
21
  /**
@@ -36,6 +37,9 @@ export class VIB3Engine {
36
37
  /** @type {boolean} Debug mode */
37
38
  this.debug = options.debug || false;
38
39
 
40
+ /** @type {VitalitySystem} Global breathing rhythm */
41
+ this.vitality = new VitalitySystem();
42
+
39
43
  /** @type {ReactivityManager} Reactivity system for audio/tilt/interaction */
40
44
  this.reactivity = new ReactivityManager((name, value) => {
41
45
  this.parameters.setParameter(name, value);
@@ -83,11 +87,35 @@ export class VIB3Engine {
83
87
  // Sync base parameters to reactivity manager
84
88
  this.reactivity.setBaseParameters(this.parameters.getAllParameters());
85
89
 
90
+ // Start vitality system
91
+ this.vitality.start();
92
+
93
+ // Start global loop to drive vitality updates
94
+ this._startGlobalLoop();
95
+
86
96
  this.initialized = true;
87
97
  console.log('VIB3+ Engine initialized');
88
98
  return true;
89
99
  }
90
100
 
101
+ _startGlobalLoop() {
102
+ this._globalLoopActive = true;
103
+ const loop = () => {
104
+ if (!this._globalLoopActive) return;
105
+ if (this.initialized) {
106
+ // Update breath cycle
107
+ const breath = this.vitality.update();
108
+
109
+ // Push breath to current system
110
+ if (this.activeSystem && this.activeSystem.updateParameters) {
111
+ this.activeSystem.updateParameters({ breath });
112
+ }
113
+ }
114
+ this._globalRafId = requestAnimationFrame(loop);
115
+ };
116
+ this._globalRafId = requestAnimationFrame(loop);
117
+ }
118
+
91
119
  /**
92
120
  * Create and initialize a specific system
93
121
  * CRITICAL: Engines find canvases by ID in DOM, not passed as parameters!
@@ -534,7 +562,7 @@ export class VIB3Engine {
534
562
  spatialActive: this.spatialInput.enabled,
535
563
  backend: this.getActiveBackendType(),
536
564
  timestamp: new Date().toISOString(),
537
- version: '1.2.0'
565
+ version: '2.0.3'
538
566
  };
539
567
  }
540
568
 
@@ -608,6 +636,15 @@ export class VIB3Engine {
608
636
  * Destroy engine and clean up
609
637
  */
610
638
  destroy() {
639
+ // Cancel global breath loop
640
+ this._globalLoopActive = false;
641
+ if (this._globalRafId) {
642
+ cancelAnimationFrame(this._globalRafId);
643
+ this._globalRafId = null;
644
+ }
645
+
646
+ this.vitality.stop();
647
+
611
648
  // Stop and destroy spatial input
612
649
  if (this.spatialInput) {
613
650
  this.spatialInput.destroy();
@@ -0,0 +1,53 @@
1
+ /**
2
+ * VitalitySystem.js
3
+ * Manages the "breath of life" for the VIB3+ Engine.
4
+ * Generates a global rhythmic breath cycle (Exhale/Evoke) that modulates
5
+ * all visualization systems for a unified, organic feel.
6
+ */
7
+ export class VitalitySystem {
8
+ constructor() {
9
+ this.time = 0;
10
+ this.breath = 0;
11
+ this.cycleDuration = 6000; // 6 seconds per breath
12
+ this.isRunning = false;
13
+ }
14
+
15
+ start() {
16
+ this.isRunning = true;
17
+ this.startTime = Date.now();
18
+ }
19
+
20
+ stop() {
21
+ this.isRunning = false;
22
+ }
23
+
24
+ /**
25
+ * Update the breath cycle.
26
+ * Returns a normalized 0-1 value representing the breath phase.
27
+ * 0 = Empty, 1 = Full
28
+ * Uses a sine wave for smooth organic motion.
29
+ */
30
+ update(deltaTime) {
31
+ if (!this.isRunning) return 0;
32
+
33
+ const now = Date.now();
34
+ const elapsed = now - this.startTime;
35
+
36
+ // 0 to 2PI over cycleDuration
37
+ const phase = (elapsed % this.cycleDuration) / this.cycleDuration;
38
+ const angle = phase * Math.PI * 2;
39
+
40
+ // Smooth sine wave: -1 to 1 -> 0 to 1
41
+ // We use -cos to start at 0 (empty), go to 1 (full), back to 0
42
+ this.breath = (1.0 - Math.cos(angle)) * 0.5;
43
+
44
+ // Add a small "pause" at the top and bottom for realism?
45
+ // For now, pure sine is hypnotic enough.
46
+
47
+ return this.breath;
48
+ }
49
+
50
+ getBreath() {
51
+ return this.breath;
52
+ }
53
+ }
@@ -1,8 +1,8 @@
1
1
  import { RendererContract } from '../RendererContracts.js';
2
- import { HolographicSystem } from '../../holograms/HolographicSystem.js';
2
+ import { RealHolographicSystem } from '../../holograms/RealHolographicSystem.js';
3
3
 
4
4
  export class HolographicRendererAdapter extends RendererContract {
5
- constructor(system = new HolographicSystem({ autoStart: false })) {
5
+ constructor(system = new RealHolographicSystem({ autoStart: false })) {
6
6
  super();
7
7
  this.system = system;
8
8
  }