@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.
- package/CHANGELOG.md +36 -0
- package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +243 -0
- package/DOCS/CLI_ONBOARDING.md +1 -1
- package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +117 -0
- package/DOCS/EPIC_SCROLL_EVENTS.md +773 -0
- package/DOCS/HANDOFF_LANDING_PAGE.md +154 -0
- package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +493 -0
- package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +937 -0
- package/DOCS/PRODUCT_STRATEGY.md +63 -0
- package/DOCS/README.md +103 -0
- package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +97 -0
- package/DOCS/ROADMAP.md +111 -0
- package/DOCS/SCROLL_TIMELINE_v3.md +269 -0
- package/DOCS/SITE_REFACTOR_PLAN.md +100 -0
- package/DOCS/STATUS.md +24 -0
- package/DOCS/SYSTEM_INVENTORY.md +33 -30
- package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +85 -0
- package/DOCS/VISUAL_ANALYSIS_FACETAD.md +133 -0
- package/DOCS/VISUAL_ANALYSIS_SIMONE.md +95 -0
- package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +86 -0
- package/DOCS/{BLUEPRINT_EXECUTION_PLAN_2026-01-07.md → archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md} +1 -1
- package/DOCS/{DEV_TRACK_ANALYSIS.md → archive/DEV_TRACK_ANALYSIS.md} +3 -0
- package/DOCS/{SYSTEM_AUDIT_2026-01-30.md → archive/SYSTEM_AUDIT_2026-01-30.md} +3 -0
- package/DOCS/{DEV_TRACK_SESSION_2026-01-31.md → dev-tracks/DEV_TRACK_SESSION_2026-01-31.md} +1 -1
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +231 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +127 -0
- package/DOCS/dev-tracks/README.md +10 -0
- package/README.md +26 -13
- package/cpp/CMakeLists.txt +236 -0
- package/cpp/bindings/embind.cpp +269 -0
- package/cpp/build.sh +129 -0
- package/cpp/geometry/Crystal.cpp +103 -0
- package/cpp/geometry/Fractal.cpp +136 -0
- package/cpp/geometry/GeometryGenerator.cpp +262 -0
- package/cpp/geometry/KleinBottle.cpp +71 -0
- package/cpp/geometry/Sphere.cpp +134 -0
- package/cpp/geometry/Tesseract.cpp +94 -0
- package/cpp/geometry/Tetrahedron.cpp +83 -0
- package/cpp/geometry/Torus.cpp +65 -0
- package/cpp/geometry/WarpFunctions.cpp +238 -0
- package/cpp/geometry/Wave.cpp +85 -0
- package/cpp/include/vib3_ffi.h +238 -0
- package/cpp/math/Mat4x4.cpp +409 -0
- package/cpp/math/Mat4x4.hpp +209 -0
- package/cpp/math/Projection.cpp +142 -0
- package/cpp/math/Projection.hpp +148 -0
- package/cpp/math/Rotor4D.cpp +322 -0
- package/cpp/math/Rotor4D.hpp +204 -0
- package/cpp/math/Vec4.cpp +303 -0
- package/cpp/math/Vec4.hpp +225 -0
- package/cpp/src/vib3_ffi.cpp +607 -0
- package/cpp/tests/Geometry_test.cpp +213 -0
- package/cpp/tests/Mat4x4_test.cpp +494 -0
- package/cpp/tests/Projection_test.cpp +298 -0
- package/cpp/tests/Rotor4D_test.cpp +423 -0
- package/cpp/tests/Vec4_test.cpp +489 -0
- package/package.json +31 -27
- package/src/agent/mcp/MCPServer.js +722 -0
- package/src/agent/mcp/stdio-server.js +264 -0
- package/src/agent/mcp/tools.js +367 -0
- package/src/cli/index.js +0 -0
- package/src/core/CanvasManager.js +97 -204
- package/src/core/ErrorReporter.js +1 -1
- package/src/core/Parameters.js +1 -1
- package/src/core/VIB3Engine.js +38 -1
- package/src/core/VitalitySystem.js +53 -0
- package/src/core/renderers/HolographicRendererAdapter.js +2 -2
- package/src/creative/AestheticMapper.js +628 -0
- package/src/creative/ChoreographyPlayer.js +481 -0
- package/src/export/TradingCardManager.js +3 -4
- package/src/faceted/FacetedSystem.js +237 -388
- package/src/holograms/HolographicVisualizer.js +29 -12
- package/src/holograms/RealHolographicSystem.js +68 -12
- package/src/polychora/PolychoraSystem.js +77 -0
- package/src/quantum/QuantumEngine.js +103 -66
- package/src/quantum/QuantumVisualizer.js +7 -2
- package/src/render/UnifiedRenderBridge.js +3 -0
- package/src/shaders/faceted/faceted.frag.glsl +220 -80
- package/src/shaders/faceted/faceted.frag.wgsl +138 -97
- package/src/shaders/holographic/holographic.frag.glsl +28 -9
- package/src/shaders/holographic/holographic.frag.wgsl +107 -38
- package/src/shaders/quantum/quantum.frag.glsl +1 -0
- package/src/shaders/quantum/quantum.frag.wgsl +1 -1
- package/src/viewer/index.js +1 -1
- package/tools/headless-renderer.js +258 -0
- package/tools/shader-sync-verify.js +8 -4
- package/tools/site-analysis/all-reports.json +32 -0
- package/tools/site-analysis/combined-analysis.md +50 -0
- package/tools/site-analyzer.mjs +779 -0
- package/tools/visual-catalog/capture.js +276 -0
- package/tools/visual-catalog/composite.js +138 -0
- /package/DOCS/{DEV_TRACK_PLAN_2026-01-07.md → archive/DEV_TRACK_PLAN_2026-01-07.md} +0 -0
- /package/DOCS/{SESSION_014_PLAN.md → archive/SESSION_014_PLAN.md} +0 -0
- /package/DOCS/{SESSION_LOG_2026-01-07.md → archive/SESSION_LOG_2026-01-07.md} +0 -0
- /package/DOCS/{STRATEGIC_BLUEPRINT_2026-01-07.md → archive/STRATEGIC_BLUEPRINT_2026-01-07.md} +0 -0
- /package/src/viewer/{ReactivityManager.js → ViewerInputHandler.js} +0 -0
|
@@ -1,217 +1,110 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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.
|
|
89
|
+
sdkVersion: '2.0.3',
|
|
90
90
|
};
|
|
91
91
|
|
|
92
92
|
// Custom callback takes priority
|
package/src/core/Parameters.js
CHANGED
|
@@ -272,7 +272,7 @@ export class ParameterManager {
|
|
|
272
272
|
exportConfiguration() {
|
|
273
273
|
return {
|
|
274
274
|
type: 'vib34d-integrated-config',
|
|
275
|
-
version: '
|
|
275
|
+
version: '2.0.3',
|
|
276
276
|
timestamp: new Date().toISOString(),
|
|
277
277
|
name: `VIB34D Config ${new Date().toLocaleDateString()}`,
|
|
278
278
|
parameters: { ...this.params }
|
package/src/core/VIB3Engine.js
CHANGED
|
@@ -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: '
|
|
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 {
|
|
2
|
+
import { RealHolographicSystem } from '../../holograms/RealHolographicSystem.js';
|
|
3
3
|
|
|
4
4
|
export class HolographicRendererAdapter extends RendererContract {
|
|
5
|
-
constructor(system = new
|
|
5
|
+
constructor(system = new RealHolographicSystem({ autoStart: false })) {
|
|
6
6
|
super();
|
|
7
7
|
this.system = system;
|
|
8
8
|
}
|