@vib3code/sdk 2.0.1

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 (258) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
  3. package/DOCS/CI_TESTING.md +38 -0
  4. package/DOCS/CLI_ONBOARDING.md +75 -0
  5. package/DOCS/CONTROL_REFERENCE.md +64 -0
  6. package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
  7. package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
  8. package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
  9. package/DOCS/ENV_SETUP.md +189 -0
  10. package/DOCS/EXPORT_FORMATS.md +417 -0
  11. package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
  12. package/DOCS/LICENSING_TIERS.md +275 -0
  13. package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
  14. package/DOCS/OBS_SETUP_GUIDE.md +98 -0
  15. package/DOCS/PROJECT_SETUP.md +66 -0
  16. package/DOCS/RENDERER_LIFECYCLE.md +40 -0
  17. package/DOCS/REPO_MANIFEST.md +121 -0
  18. package/DOCS/SESSION_014_PLAN.md +195 -0
  19. package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
  20. package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
  21. package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
  22. package/DOCS/SYSTEM_INVENTORY.md +520 -0
  23. package/DOCS/TELEMETRY_EXPORTS.md +34 -0
  24. package/DOCS/WEBGPU_STATUS.md +38 -0
  25. package/DOCS/XR_BENCHMARKS.md +608 -0
  26. package/LICENSE +21 -0
  27. package/README.md +426 -0
  28. package/docs/.nojekyll +0 -0
  29. package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
  30. package/docs/02-hyperspatial_ego_death.html +346 -0
  31. package/docs/03-post_cartesian_sublime.html +346 -0
  32. package/docs/04-crystalline_void_meditation.html +346 -0
  33. package/docs/05-quantum_decoherence_ballet.html +346 -0
  34. package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
  35. package/docs/07-hyperspatial_ego_death.html +346 -0
  36. package/docs/08-post_cartesian_sublime.html +346 -0
  37. package/docs/09-crystalline_void_meditation.html +346 -0
  38. package/docs/10-quantum_decoherence_ballet.html +346 -0
  39. package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
  40. package/docs/12-hyperspatial_ego_death.html +346 -0
  41. package/docs/13-post_cartesian_sublime.html +346 -0
  42. package/docs/index.html +794 -0
  43. package/docs/test-hub.html +441 -0
  44. package/docs/url-state.js +102 -0
  45. package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
  46. package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
  47. package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
  48. package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
  49. package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
  50. package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
  51. package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
  52. package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
  53. package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
  54. package/docs/vib3-exports/index.html +238 -0
  55. package/docs/webgpu-live.html +702 -0
  56. package/package.json +367 -0
  57. package/src/advanced/AIPresetGenerator.js +777 -0
  58. package/src/advanced/MIDIController.js +703 -0
  59. package/src/advanced/OffscreenWorker.js +1051 -0
  60. package/src/advanced/WebGPUCompute.js +1051 -0
  61. package/src/advanced/WebXRRenderer.js +680 -0
  62. package/src/agent/cli/AgentCLI.js +615 -0
  63. package/src/agent/cli/index.js +14 -0
  64. package/src/agent/index.js +73 -0
  65. package/src/agent/mcp/MCPServer.js +950 -0
  66. package/src/agent/mcp/index.js +9 -0
  67. package/src/agent/mcp/tools.js +548 -0
  68. package/src/agent/telemetry/EventStream.js +669 -0
  69. package/src/agent/telemetry/Instrumentation.js +618 -0
  70. package/src/agent/telemetry/TelemetryExporters.js +427 -0
  71. package/src/agent/telemetry/TelemetryService.js +464 -0
  72. package/src/agent/telemetry/index.js +52 -0
  73. package/src/benchmarks/BenchmarkRunner.js +381 -0
  74. package/src/benchmarks/MetricsCollector.js +299 -0
  75. package/src/benchmarks/index.js +9 -0
  76. package/src/benchmarks/scenes.js +259 -0
  77. package/src/cli/index.js +675 -0
  78. package/src/config/ApiConfig.js +88 -0
  79. package/src/core/CanvasManager.js +217 -0
  80. package/src/core/ErrorReporter.js +117 -0
  81. package/src/core/ParameterMapper.js +333 -0
  82. package/src/core/Parameters.js +396 -0
  83. package/src/core/RendererContracts.js +200 -0
  84. package/src/core/UnifiedResourceManager.js +370 -0
  85. package/src/core/VIB3Engine.js +636 -0
  86. package/src/core/renderers/FacetedRendererAdapter.js +32 -0
  87. package/src/core/renderers/HolographicRendererAdapter.js +29 -0
  88. package/src/core/renderers/QuantumRendererAdapter.js +29 -0
  89. package/src/core/renderers/RendererLifecycleManager.js +63 -0
  90. package/src/creative/ColorPresetsSystem.js +980 -0
  91. package/src/creative/ParameterTimeline.js +1061 -0
  92. package/src/creative/PostProcessingPipeline.js +1113 -0
  93. package/src/creative/TransitionAnimator.js +683 -0
  94. package/src/export/CSSExporter.js +226 -0
  95. package/src/export/CardGeneratorBase.js +279 -0
  96. package/src/export/ExportManager.js +580 -0
  97. package/src/export/FacetedCardGenerator.js +279 -0
  98. package/src/export/HolographicCardGenerator.js +543 -0
  99. package/src/export/LottieExporter.js +552 -0
  100. package/src/export/QuantumCardGenerator.js +315 -0
  101. package/src/export/SVGExporter.js +519 -0
  102. package/src/export/ShaderExporter.js +903 -0
  103. package/src/export/TradingCardGenerator.js +3055 -0
  104. package/src/export/TradingCardManager.js +181 -0
  105. package/src/export/VIB3PackageExporter.js +559 -0
  106. package/src/export/index.js +14 -0
  107. package/src/export/systems/TradingCardSystemFaceted.js +494 -0
  108. package/src/export/systems/TradingCardSystemHolographic.js +452 -0
  109. package/src/export/systems/TradingCardSystemQuantum.js +411 -0
  110. package/src/faceted/FacetedSystem.js +963 -0
  111. package/src/features/CollectionManager.js +433 -0
  112. package/src/gallery/CollectionManager.js +240 -0
  113. package/src/gallery/GallerySystem.js +485 -0
  114. package/src/geometry/GeometryFactory.js +314 -0
  115. package/src/geometry/GeometryLibrary.js +72 -0
  116. package/src/geometry/buffers/BufferBuilder.js +338 -0
  117. package/src/geometry/buffers/index.js +18 -0
  118. package/src/geometry/generators/Crystal.js +420 -0
  119. package/src/geometry/generators/Fractal.js +298 -0
  120. package/src/geometry/generators/KleinBottle.js +197 -0
  121. package/src/geometry/generators/Sphere.js +192 -0
  122. package/src/geometry/generators/Tesseract.js +160 -0
  123. package/src/geometry/generators/Tetrahedron.js +225 -0
  124. package/src/geometry/generators/Torus.js +304 -0
  125. package/src/geometry/generators/Wave.js +341 -0
  126. package/src/geometry/index.js +142 -0
  127. package/src/geometry/warp/HypersphereCore.js +211 -0
  128. package/src/geometry/warp/HypertetraCore.js +386 -0
  129. package/src/geometry/warp/index.js +57 -0
  130. package/src/holograms/HolographicVisualizer.js +1073 -0
  131. package/src/holograms/RealHolographicSystem.js +966 -0
  132. package/src/holograms/variantRegistry.js +69 -0
  133. package/src/integrations/FigmaPlugin.js +854 -0
  134. package/src/integrations/OBSMode.js +754 -0
  135. package/src/integrations/ThreeJsPackage.js +660 -0
  136. package/src/integrations/TouchDesignerExport.js +552 -0
  137. package/src/integrations/frameworks/Vib3React.js +591 -0
  138. package/src/integrations/frameworks/Vib3Svelte.js +654 -0
  139. package/src/integrations/frameworks/Vib3Vue.js +628 -0
  140. package/src/llm/LLMParameterInterface.js +240 -0
  141. package/src/llm/LLMParameterUI.js +577 -0
  142. package/src/math/Mat4x4.js +708 -0
  143. package/src/math/Projection.js +341 -0
  144. package/src/math/Rotor4D.js +637 -0
  145. package/src/math/Vec4.js +476 -0
  146. package/src/math/constants.js +164 -0
  147. package/src/math/index.js +68 -0
  148. package/src/math/projections.js +54 -0
  149. package/src/math/rotations.js +196 -0
  150. package/src/quantum/QuantumEngine.js +906 -0
  151. package/src/quantum/QuantumVisualizer.js +1103 -0
  152. package/src/reactivity/ReactivityConfig.js +499 -0
  153. package/src/reactivity/ReactivityManager.js +586 -0
  154. package/src/reactivity/SpatialInputSystem.js +1783 -0
  155. package/src/reactivity/index.js +93 -0
  156. package/src/render/CommandBuffer.js +465 -0
  157. package/src/render/MultiCanvasBridge.js +340 -0
  158. package/src/render/RenderCommand.js +514 -0
  159. package/src/render/RenderResourceRegistry.js +523 -0
  160. package/src/render/RenderState.js +552 -0
  161. package/src/render/RenderTarget.js +512 -0
  162. package/src/render/ShaderLoader.js +253 -0
  163. package/src/render/ShaderProgram.js +599 -0
  164. package/src/render/UnifiedRenderBridge.js +496 -0
  165. package/src/render/backends/WebGLBackend.js +1108 -0
  166. package/src/render/backends/WebGPUBackend.js +1409 -0
  167. package/src/render/commands/CommandBufferExecutor.js +607 -0
  168. package/src/render/commands/RenderCommandBuffer.js +661 -0
  169. package/src/render/commands/index.js +17 -0
  170. package/src/render/index.js +367 -0
  171. package/src/scene/Disposable.js +498 -0
  172. package/src/scene/MemoryPool.js +618 -0
  173. package/src/scene/Node4D.js +697 -0
  174. package/src/scene/ResourceManager.js +599 -0
  175. package/src/scene/Scene4D.js +540 -0
  176. package/src/scene/index.js +98 -0
  177. package/src/schemas/error.schema.json +84 -0
  178. package/src/schemas/extension.schema.json +88 -0
  179. package/src/schemas/index.js +214 -0
  180. package/src/schemas/parameters.schema.json +142 -0
  181. package/src/schemas/tool-pack.schema.json +44 -0
  182. package/src/schemas/tool-response.schema.json +127 -0
  183. package/src/shaders/common/fullscreen.vert.glsl +5 -0
  184. package/src/shaders/common/fullscreen.vert.wgsl +17 -0
  185. package/src/shaders/common/geometry24.glsl +65 -0
  186. package/src/shaders/common/geometry24.wgsl +54 -0
  187. package/src/shaders/common/rotation4d.glsl +85 -0
  188. package/src/shaders/common/rotation4d.wgsl +86 -0
  189. package/src/shaders/common/uniforms.glsl +44 -0
  190. package/src/shaders/common/uniforms.wgsl +48 -0
  191. package/src/shaders/faceted/faceted.frag.glsl +129 -0
  192. package/src/shaders/faceted/faceted.frag.wgsl +164 -0
  193. package/src/shaders/holographic/holographic.frag.glsl +406 -0
  194. package/src/shaders/holographic/holographic.frag.wgsl +185 -0
  195. package/src/shaders/quantum/quantum.frag.glsl +513 -0
  196. package/src/shaders/quantum/quantum.frag.wgsl +361 -0
  197. package/src/testing/ParallelTestFramework.js +519 -0
  198. package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
  199. package/src/testing/exportFormats.test.js +8 -0
  200. package/src/testing/projections.test.js +14 -0
  201. package/src/testing/rotations.test.js +37 -0
  202. package/src/ui/InteractivityMenu.js +516 -0
  203. package/src/ui/StatusManager.js +96 -0
  204. package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
  205. package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
  206. package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
  207. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
  208. package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
  209. package/src/variations/VariationManager.js +431 -0
  210. package/src/viewer/AudioReactivity.js +505 -0
  211. package/src/viewer/CardBending.js +481 -0
  212. package/src/viewer/GalleryUI.js +832 -0
  213. package/src/viewer/ReactivityManager.js +590 -0
  214. package/src/viewer/TradingCardExporter.js +600 -0
  215. package/src/viewer/ViewerPortal.js +374 -0
  216. package/src/viewer/index.js +12 -0
  217. package/src/wasm/WasmLoader.js +296 -0
  218. package/src/wasm/index.js +132 -0
  219. package/tools/agentic/mcpTools.js +88 -0
  220. package/tools/cli/agent-cli.js +92 -0
  221. package/tools/export/formats.js +24 -0
  222. package/tools/math/rotation-baseline.mjs +64 -0
  223. package/tools/shader-sync-verify.js +937 -0
  224. package/tools/telemetry/manifestPipeline.js +141 -0
  225. package/tools/telemetry/telemetryEvents.js +35 -0
  226. package/types/adaptive-sdk.d.ts +185 -0
  227. package/types/advanced/AIPresetGenerator.d.ts +81 -0
  228. package/types/advanced/MIDIController.d.ts +100 -0
  229. package/types/advanced/OffscreenWorker.d.ts +82 -0
  230. package/types/advanced/WebGPUCompute.d.ts +52 -0
  231. package/types/advanced/WebXRRenderer.d.ts +77 -0
  232. package/types/advanced/index.d.ts +46 -0
  233. package/types/core/ErrorReporter.d.ts +50 -0
  234. package/types/core/VIB3Engine.d.ts +204 -0
  235. package/types/creative/ColorPresetsSystem.d.ts +91 -0
  236. package/types/creative/ParameterTimeline.d.ts +74 -0
  237. package/types/creative/PostProcessingPipeline.d.ts +109 -0
  238. package/types/creative/TransitionAnimator.d.ts +71 -0
  239. package/types/creative/index.d.ts +35 -0
  240. package/types/integrations/FigmaPlugin.d.ts +46 -0
  241. package/types/integrations/OBSMode.d.ts +74 -0
  242. package/types/integrations/ThreeJsPackage.d.ts +62 -0
  243. package/types/integrations/TouchDesignerExport.d.ts +36 -0
  244. package/types/integrations/Vib3React.d.ts +74 -0
  245. package/types/integrations/Vib3Svelte.d.ts +63 -0
  246. package/types/integrations/Vib3Vue.d.ts +55 -0
  247. package/types/integrations/index.d.ts +52 -0
  248. package/types/reactivity/SpatialInputSystem.d.ts +173 -0
  249. package/types/reactivity/index.d.ts +394 -0
  250. package/types/render/CommandBuffer.d.ts +169 -0
  251. package/types/render/RenderCommand.d.ts +312 -0
  252. package/types/render/RenderState.d.ts +279 -0
  253. package/types/render/RenderTarget.d.ts +254 -0
  254. package/types/render/ShaderProgram.d.ts +277 -0
  255. package/types/render/UnifiedRenderBridge.d.ts +143 -0
  256. package/types/render/WebGLBackend.d.ts +168 -0
  257. package/types/render/WebGPUBackend.d.ts +186 -0
  258. package/types/render/index.d.ts +141 -0
@@ -0,0 +1,906 @@
1
+ /**
2
+ * VIB34D Quantum Engine
3
+ * Manages the enhanced quantum system with complex 3D lattice functions
4
+ */
5
+
6
+ import { QuantumHolographicVisualizer } from './QuantumVisualizer.js';
7
+ import { ParameterManager } from '../core/Parameters.js';
8
+ import { GeometryLibrary } from '../geometry/GeometryLibrary.js';
9
+ import { MultiCanvasBridge } from '../render/MultiCanvasBridge.js';
10
+ import { shaderLoader } from '../render/ShaderLoader.js';
11
+
12
+ export class QuantumEngine {
13
+ constructor(options = {}) {
14
+ console.log('🔮 Initializing VIB34D Quantum Engine...');
15
+
16
+ this.visualizers = [];
17
+ this.parameters = new ParameterManager();
18
+ this.isActive = false;
19
+ this.autoStart = options.autoStart ?? true;
20
+
21
+ // Canvas override for single-canvas multi-instance mode
22
+ /** @type {HTMLCanvasElement|null} */
23
+ this.canvasOverride = options.canvas || null;
24
+
25
+ // Bridge rendering state
26
+ /** @type {MultiCanvasBridge|null} */
27
+ this._multiCanvasBridge = null;
28
+ /** @type {'direct'|'bridge'} */
29
+ this._renderMode = 'direct';
30
+ /** @type {number} time accumulator for bridge rendering (ms) */
31
+ this._bridgeTime = 0;
32
+
33
+ // Conditional reactivity: Use built-in only if ReactivityManager not active
34
+ this.useBuiltInReactivity = !window.reactivityManager;
35
+
36
+ // Gesture velocity reactivity system for Quantum
37
+ this.lastMousePosition = { x: 0.5, y: 0.5 };
38
+ this.mouseVelocity = { x: 0, y: 0 };
39
+ this.velocityHistory = [];
40
+ this.maxVelocityHistory = 10;
41
+
42
+ // Base parameter values for gesture modulation
43
+ this.baseHue = 280; // Purple-blue for quantum
44
+ this.baseMorphFactor = 1.0;
45
+
46
+ // Initialize with quantum-enhanced defaults
47
+ this.parameters.setParameter('hue', this.baseHue);
48
+ this.parameters.setParameter('intensity', 0.7); // Higher intensity
49
+ this.parameters.setParameter('saturation', 0.9); // More vivid
50
+ this.parameters.setParameter('gridDensity', 20); // Denser patterns
51
+ this.parameters.setParameter('morphFactor', this.baseMorphFactor);
52
+
53
+ this.init();
54
+ }
55
+
56
+ /**
57
+ * Initialize the quantum system
58
+ */
59
+ init() {
60
+ this.createVisualizers();
61
+ this.setupAudioReactivity();
62
+ this.setupGestureVelocityReactivity(); // Additional gesture system
63
+ if (this.autoStart) {
64
+ this.startRenderLoop();
65
+ }
66
+ console.log('✨ Quantum Engine initialized with audio + gesture velocity reactivity');
67
+ }
68
+
69
+ /**
70
+ * Create quantum visualizers for all 5 layers, or a single content-layer
71
+ * visualizer when canvasOverride is provided.
72
+ */
73
+ createVisualizers() {
74
+ // Single-canvas override mode: lightweight content-only layer
75
+ if (this.canvasOverride) {
76
+ try {
77
+ const visualizer = new QuantumHolographicVisualizer(
78
+ this.canvasOverride, 'content', 1.0, 0
79
+ );
80
+ if (visualizer.gl) {
81
+ this.visualizers.push(visualizer);
82
+ console.log('🌌 Created quantum single-canvas visualizer (content layer)');
83
+ } else {
84
+ console.warn('⚠️ No WebGL context for quantum canvasOverride');
85
+ }
86
+ } catch (error) {
87
+ console.warn('Failed to create quantum single-canvas visualizer:', error);
88
+ }
89
+ return;
90
+ }
91
+
92
+ const layers = [
93
+ { id: 'quantum-background-canvas', role: 'background', reactivity: 0.4 },
94
+ { id: 'quantum-shadow-canvas', role: 'shadow', reactivity: 0.6 },
95
+ { id: 'quantum-content-canvas', role: 'content', reactivity: 1.0 },
96
+ { id: 'quantum-highlight-canvas', role: 'highlight', reactivity: 1.3 },
97
+ { id: 'quantum-accent-canvas', role: 'accent', reactivity: 1.6 }
98
+ ];
99
+
100
+ layers.forEach(layer => {
101
+ try {
102
+ // Canvas elements should already exist in HTML
103
+ const canvas = document.getElementById(layer.id);
104
+ if (!canvas) {
105
+ console.warn(`⚠️ Canvas ${layer.id} not found in DOM - skipping`);
106
+ return;
107
+ }
108
+
109
+ const visualizer = new QuantumHolographicVisualizer(layer.id, layer.role, layer.reactivity, 0);
110
+ if (visualizer.gl) {
111
+ this.visualizers.push(visualizer);
112
+ console.log(`🌌 Created quantum layer: ${layer.role}`);
113
+ } else {
114
+ console.warn(`⚠️ No WebGL context for quantum layer ${layer.id}`);
115
+ }
116
+ } catch (error) {
117
+ console.warn(`Failed to create quantum layer ${layer.id}:`, error);
118
+ }
119
+ });
120
+
121
+ console.log(`✅ Created ${this.visualizers.length} quantum visualizers with enhanced effects`);
122
+ }
123
+
124
+ /**
125
+ * Initialize the Quantum system through UnifiedRenderBridge / MultiCanvasBridge.
126
+ * This wires all 5 layers through the bridge for WebGL/WebGPU abstraction.
127
+ * Falls back to direct WebGL if bridge initialization fails.
128
+ *
129
+ * @param {object} [options]
130
+ * @param {boolean} [options.preferWebGPU=true] - Try WebGPU first, fall back to WebGL
131
+ * @param {boolean} [options.debug=false]
132
+ * @returns {Promise<boolean>} True if bridge mode activated
133
+ */
134
+ async initWithBridge(options = {}) {
135
+ try {
136
+ const bridge = await this.createMultiCanvasBridge(options);
137
+ if (bridge && bridge.initialized) {
138
+ this._renderMode = 'bridge';
139
+ this._bridgeTime = 0;
140
+ console.log(`Quantum System initialized via ${bridge.backendType} bridge (${bridge.layerCount} layers)`);
141
+ return true;
142
+ }
143
+ console.warn('Quantum bridge init returned no bridge, staying in direct mode');
144
+ return false;
145
+ } catch (e) {
146
+ console.error('Quantum bridge init failed, staying in direct mode:', e);
147
+ this._renderMode = 'direct';
148
+ return false;
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Create a MultiCanvasBridge for WebGPU rendering.
154
+ * Returns a configured bridge with quantum shaders compiled on all layers.
155
+ *
156
+ * @param {object} [options]
157
+ * @param {boolean} [options.preferWebGPU=true]
158
+ * @returns {Promise<MultiCanvasBridge|null>}
159
+ */
160
+ async createMultiCanvasBridge(options = {}) {
161
+ const canvasMap = {};
162
+ const layerIds = {
163
+ background: 'quantum-background-canvas',
164
+ shadow: 'quantum-shadow-canvas',
165
+ content: 'quantum-content-canvas',
166
+ highlight: 'quantum-highlight-canvas',
167
+ accent: 'quantum-accent-canvas'
168
+ };
169
+
170
+ for (const [role, id] of Object.entries(layerIds)) {
171
+ const el = document.getElementById(id);
172
+ if (el) canvasMap[role] = el;
173
+ }
174
+
175
+ if (Object.keys(canvasMap).length === 0) return null;
176
+
177
+ const bridge = new MultiCanvasBridge();
178
+ await bridge.initialize({ canvases: canvasMap, preferWebGPU: options.preferWebGPU !== false });
179
+
180
+ // Load external shader files, fall back to inline sources if unavailable
181
+ let sources = {
182
+ glslVertex: 'attribute vec2 a_position;\nvoid main() { gl_Position = vec4(a_position, 0.0, 1.0); }',
183
+ glslFragment: null,
184
+ wgslFragment: null
185
+ };
186
+
187
+ try {
188
+ const external = await shaderLoader.loadShaderPair('quantum', 'quantum/quantum.frag');
189
+ if (external.glslVertex) sources.glslVertex = external.glslVertex;
190
+ if (external.glslFragment) sources.glslFragment = external.glslFragment;
191
+ if (external.wgslFragment) sources.wgslFragment = external.wgslFragment;
192
+ } catch (loadErr) {
193
+ console.warn('Quantum external shader load failed, using inline fallback');
194
+ }
195
+
196
+ if (sources.glslFragment || sources.wgslFragment) {
197
+ const result = bridge.compileShaderAll('quantum', sources);
198
+ if (result.failed.length > 0) {
199
+ console.warn(`Quantum shader compilation failed on layers: ${result.failed.join(', ')}`);
200
+ }
201
+ }
202
+
203
+ this._multiCanvasBridge = bridge;
204
+ return bridge;
205
+ }
206
+
207
+ /**
208
+ * Build the VIB3+ standard uniform object from current parameters.
209
+ * Used by bridge rendering to send uniforms to external shader programs.
210
+ * @private
211
+ * @returns {object}
212
+ */
213
+ _buildSharedUniforms() {
214
+ const params = this.parameters.getAllParameters();
215
+ const audioData = window.audioReactive || { bass: 0, mid: 0, high: 0 };
216
+
217
+ return {
218
+ u_time: this._bridgeTime,
219
+ u_resolution: null, // Set per-layer by MultiCanvasBridge
220
+ u_geometry: params.geometry || 0,
221
+ u_rot4dXY: params.rot4dXY || 0,
222
+ u_rot4dXZ: params.rot4dXZ || 0,
223
+ u_rot4dYZ: params.rot4dYZ || 0,
224
+ u_rot4dXW: params.rot4dXW || 0,
225
+ u_rot4dYW: params.rot4dYW || 0,
226
+ u_rot4dZW: params.rot4dZW || 0,
227
+ u_dimension: params.dimension || 3.5,
228
+ u_gridDensity: params.gridDensity || 20,
229
+ u_morphFactor: params.morphFactor || 1.0,
230
+ u_chaos: params.chaos || 0.2,
231
+ u_speed: params.speed || 1.0,
232
+ u_hue: params.hue || 280,
233
+ u_intensity: params.intensity || 0.7,
234
+ u_saturation: params.saturation || 0.9,
235
+ u_mouseIntensity: 0,
236
+ u_clickIntensity: this.clickFlashIntensity || 0,
237
+ u_bass: audioData.bass || 0,
238
+ u_mid: audioData.mid || 0,
239
+ u_high: audioData.high || 0
240
+ };
241
+ }
242
+
243
+ /**
244
+ * Render a single frame via the MultiCanvasBridge.
245
+ * Sets shared uniforms and renders all 5 layers with the external quantum shader.
246
+ * @private
247
+ */
248
+ _renderBridgeFrame() {
249
+ if (!this._multiCanvasBridge || !this._multiCanvasBridge.initialized) return;
250
+
251
+ this._bridgeTime += 16; // ~60fps increment
252
+
253
+ const uniforms = this._buildSharedUniforms();
254
+
255
+ // Set canvas resolution per layer before rendering
256
+ for (const layerName of this._multiCanvasBridge.layerNames) {
257
+ const bridge = this._multiCanvasBridge.getBridge(layerName);
258
+ if (bridge && bridge.canvas) {
259
+ this._multiCanvasBridge.setLayerUniforms(layerName, {
260
+ u_resolution: [bridge.canvas.width, bridge.canvas.height]
261
+ });
262
+ }
263
+ }
264
+
265
+ this._multiCanvasBridge.setSharedUniforms(uniforms);
266
+ this._multiCanvasBridge.renderAll('quantum', { clearColor: [0, 0, 0, 0] });
267
+ }
268
+
269
+ /**
270
+ * Set system active/inactive
271
+ */
272
+ setActive(active) {
273
+ this.isActive = active;
274
+
275
+ if (active) {
276
+ // Show quantum layers (skip in single-canvas override mode)
277
+ if (!this.canvasOverride) {
278
+ const quantumLayers = document.getElementById('quantumLayers');
279
+ if (quantumLayers) {
280
+ quantumLayers.style.display = 'block';
281
+ }
282
+ }
283
+
284
+ // Enable audio if global audio is enabled
285
+ if (window.audioEnabled && !this.audioEnabled) {
286
+ this.enableAudio();
287
+ }
288
+
289
+ console.log('🔮 Quantum System ACTIVATED - Audio frequency reactivity mode');
290
+ } else {
291
+ // Hide quantum layers (skip in single-canvas override mode)
292
+ if (!this.canvasOverride) {
293
+ const quantumLayers = document.getElementById('quantumLayers');
294
+ if (quantumLayers) {
295
+ quantumLayers.style.display = 'none';
296
+ }
297
+ }
298
+ console.log('🔮 Quantum System DEACTIVATED');
299
+ }
300
+ }
301
+
302
+ // Method to be called when global audio is toggled
303
+ toggleAudio(enabled) {
304
+ if (enabled && this.isActive && !this.audioEnabled) {
305
+ this.enableAudio();
306
+ } else if (!enabled && this.audioEnabled) {
307
+ this.audioEnabled = false;
308
+ // Stop audio stream tracks to release microphone
309
+ if (this._audioStream) {
310
+ this._audioStream.getTracks().forEach(track => track.stop());
311
+ this._audioStream = null;
312
+ }
313
+ if (this.audioContext) {
314
+ this.audioContext.close().catch(() => {});
315
+ this.audioContext = null;
316
+ }
317
+ this.analyser = null;
318
+ this.frequencyData = null;
319
+ console.log('Quantum audio reactivity disabled');
320
+ }
321
+ }
322
+
323
+ /**
324
+ * Setup audio frequency reactivity for Quantum system
325
+ */
326
+ setupAudioReactivity() {
327
+ console.log('🌌 Setting up Quantum audio frequency reactivity');
328
+ // Audio setup will be triggered when audio is enabled
329
+ }
330
+
331
+ /**
332
+ * Setup enhanced multi-parameter reactivity for Quantum system
333
+ */
334
+ setupGestureVelocityReactivity() {
335
+ if (!this.useBuiltInReactivity) {
336
+ console.log('🌌 Quantum built-in reactivity DISABLED - ReactivityManager active');
337
+ return;
338
+ }
339
+ if (this.canvasOverride) {
340
+ console.log('🌌 Quantum gesture reactivity skipped (single-canvas override mode)');
341
+ return;
342
+ }
343
+
344
+ console.log('🌌 Setting up Quantum: velocity + click + scroll + multi-parameter reactivity');
345
+
346
+ // Enhanced state for smooth effects
347
+ this.clickFlashIntensity = 0;
348
+ this.scrollMorph = 1.0; // Base morph factor
349
+ this.velocitySmoothing = 0.8; // Smoother velocity transitions
350
+
351
+ const quantumCanvases = [
352
+ 'quantum-background-canvas', 'quantum-shadow-canvas', 'quantum-content-canvas',
353
+ 'quantum-highlight-canvas', 'quantum-accent-canvas'
354
+ ];
355
+
356
+ quantumCanvases.forEach(canvasId => {
357
+ const canvas = document.getElementById(canvasId);
358
+ if (!canvas) return;
359
+
360
+ // Mouse movement -> smooth velocity + multiple parameters
361
+ canvas.addEventListener('mousemove', (e) => {
362
+ if (!this.isActive) return;
363
+
364
+ const rect = canvas.getBoundingClientRect();
365
+ const mouseX = (e.clientX - rect.left) / rect.width;
366
+ const mouseY = (e.clientY - rect.top) / rect.height;
367
+
368
+ this.updateEnhancedQuantumParameters(mouseX, mouseY);
369
+ });
370
+
371
+ // Touch movement -> same enhanced parameters
372
+ canvas.addEventListener('touchmove', (e) => {
373
+ if (!this.isActive) return;
374
+ e.preventDefault();
375
+
376
+ if (e.touches.length > 0) {
377
+ const touch = e.touches[0];
378
+ const rect = canvas.getBoundingClientRect();
379
+ const touchX = (touch.clientX - rect.left) / rect.width;
380
+ const touchY = (touch.clientY - rect.top) / rect.height;
381
+
382
+ this.updateEnhancedQuantumParameters(touchX, touchY);
383
+ }
384
+ }, { passive: false });
385
+
386
+ // Click -> quantum flash effect
387
+ canvas.addEventListener('click', (e) => {
388
+ if (!this.isActive) return;
389
+ this.triggerQuantumClick();
390
+ });
391
+
392
+ // Touch end -> quantum flash effect
393
+ canvas.addEventListener('touchend', (e) => {
394
+ if (!this.isActive) return;
395
+ this.triggerQuantumClick();
396
+ });
397
+
398
+ // Wheel -> quantum morphing scroll effect
399
+ canvas.addEventListener('wheel', (e) => {
400
+ if (!this.isActive) return;
401
+ e.preventDefault();
402
+ this.updateQuantumScroll(e.deltaY);
403
+ }, { passive: false });
404
+ });
405
+
406
+ // Start smooth animation loops
407
+ this.startQuantumEffectLoops();
408
+ }
409
+
410
+ updateEnhancedQuantumParameters(x, y) {
411
+ // Calculate velocity from position change (smoother)
412
+ const deltaX = x - this.lastMousePosition.x;
413
+ const deltaY = y - this.lastMousePosition.y;
414
+ const velocity = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
415
+
416
+ // Smooth velocity history (reduced from 10 to 5 for responsiveness)
417
+ this.velocityHistory.push(velocity);
418
+ if (this.velocityHistory.length > 5) {
419
+ this.velocityHistory.shift();
420
+ }
421
+
422
+ // Calculate smoother average velocity
423
+ const avgVelocity = this.velocityHistory.reduce((sum, v) => sum + v, 0) / this.velocityHistory.length;
424
+
425
+ // EXPERIMENTAL QUANTUM MOUSE MAPPING: X-axis rotation + hemispheric colors
426
+
427
+ // X-AXIS: Direct rotation mapping (smooth 4D rotation)
428
+ // Map mouse X (0-1) to rotation angle (-π to π for full rotation range)
429
+ const rotationAngle = (x - 0.5) * Math.PI * 2; // -2π to 2π range
430
+ const rot4dXW = rotationAngle * 0.5; // Smooth XW rotation
431
+ const rot4dYW = rotationAngle * 0.3; // Complementary YW rotation
432
+ const rot4dZW = rotationAngle * 0.2; // Subtle ZW rotation
433
+
434
+ // Y-AXIS: Maintains current behavior (density/complexity)
435
+ const gridDensity = 10 + (y * 90); // Y position: 10-100 range (unchanged)
436
+
437
+ // HEMISPHERIC COLOR MAPPING: Distance from center affects color zones
438
+ const centerX = 0.5;
439
+ const centerY = 0.5;
440
+ const distanceFromCenter = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
441
+ const normalizedDistance = Math.min(1.0, distanceFromCenter * Math.sqrt(2)); // 0-1 range
442
+
443
+ // Color hemisphere mapping
444
+ const leftHemisphere = x < 0.5;
445
+ const topHemisphere = y < 0.5;
446
+
447
+ let baseHue;
448
+ if (leftHemisphere && topHemisphere) {
449
+ baseHue = 240; // Blue quadrant
450
+ } else if (!leftHemisphere && topHemisphere) {
451
+ baseHue = 300; // Purple quadrant
452
+ } else if (leftHemisphere && !topHemisphere) {
453
+ baseHue = 180; // Cyan quadrant
454
+ } else {
455
+ baseHue = 320; // Magenta quadrant
456
+ }
457
+
458
+ // Distance affects hue variation (center = pure color, edges = shifted)
459
+ const hueVariation = normalizedDistance * 60; // 0-60 degree shift
460
+ const hue = (baseHue + hueVariation) % 360;
461
+
462
+ // Other parameters influenced by movement
463
+ const chaos = Math.min(1.0, avgVelocity * 30); // Velocity affects chaos
464
+ const speed = 0.5 + Math.min(2.5, avgVelocity * 15); // Movement speed
465
+ const intensity = 0.3 + (normalizedDistance * 0.7); // Distance affects brightness
466
+
467
+ // Update all parameters for rich visual feedback
468
+ if (window.updateParameter) {
469
+ // Rotation parameters (new experimental mapping)
470
+ window.updateParameter('rot4dXW', rot4dXW.toFixed(3));
471
+ window.updateParameter('rot4dYW', rot4dYW.toFixed(3));
472
+ window.updateParameter('rot4dZW', rot4dZW.toFixed(3));
473
+
474
+ // Traditional parameters
475
+ window.updateParameter('chaos', chaos.toFixed(2));
476
+ window.updateParameter('speed', speed.toFixed(2));
477
+ window.updateParameter('gridDensity', Math.round(gridDensity));
478
+ window.updateParameter('intensity', intensity.toFixed(2));
479
+ window.updateParameter('hue', Math.round(hue));
480
+ }
481
+
482
+ // Update last position
483
+ this.lastMousePosition.x = x;
484
+ this.lastMousePosition.y = y;
485
+
486
+ console.log(`🌌 Quantum EXPERIMENTAL: X=${x.toFixed(2)}→Rot=${rotationAngle.toFixed(2)}, Y=${y.toFixed(2)}→Density=${Math.round(gridDensity)}, Dist=${normalizedDistance.toFixed(2)}→Hue=${Math.round(hue)}, Hemisphere=${leftHemisphere ? 'L' : 'R'}${topHemisphere ? 'T' : 'B'}`);
487
+ }
488
+
489
+ triggerQuantumClick() {
490
+ // DRAMATIC QUANTUM ENERGY BURST (multi-parameter)
491
+ this.clickFlashIntensity = 1.0;
492
+
493
+ // Additional dramatic quantum effects that decay back
494
+ this.quantumChaosBlast = 0.7; // Chaos energy burst
495
+ this.quantumSpeedWave = 2.0; // Speed wave effect
496
+ this.quantumHueShift = 60; // Color explosion shift
497
+
498
+ console.log('💥 Quantum energy burst: flash + chaos + speed + hue explosion');
499
+ }
500
+
501
+ updateQuantumScroll(deltaY) {
502
+ // Scroll affects morph factor smoothly
503
+ const scrollSpeed = 0.02;
504
+ const scrollDirection = deltaY > 0 ? 1 : -1;
505
+
506
+ this.scrollMorph += scrollDirection * scrollSpeed;
507
+ this.scrollMorph = Math.max(0.2, Math.min(2.0, this.scrollMorph)); // Clamp 0.2-2.0
508
+
509
+ // Update morph factor
510
+ if (window.updateParameter) {
511
+ window.updateParameter('morphFactor', this.scrollMorph.toFixed(2));
512
+ }
513
+
514
+ console.log(`🌀 Quantum scroll morph: ${this.scrollMorph.toFixed(2)}`);
515
+ }
516
+
517
+ startQuantumEffectLoops() {
518
+ const quantumEffects = () => {
519
+ let hasActiveEffects = false;
520
+
521
+ // QUANTUM FLASH EFFECT (saturation + morph)
522
+ if (this.clickFlashIntensity > 0.01) {
523
+ hasActiveEffects = true;
524
+
525
+ // Flash affects saturation - quantum shimmer effect
526
+ const flashSaturation = 0.9 + (this.clickFlashIntensity * 0.1); // 0.9-1.0 boost
527
+ const flashMorph = this.scrollMorph + (this.clickFlashIntensity * 0.5); // Morph boost
528
+
529
+ if (window.updateParameter) {
530
+ window.updateParameter('saturation', flashSaturation.toFixed(2));
531
+ window.updateParameter('morphFactor', flashMorph.toFixed(2));
532
+ }
533
+
534
+ // Smooth decay
535
+ this.clickFlashIntensity *= 0.91;
536
+ }
537
+
538
+ // DRAMATIC CHAOS BLAST EFFECT (fluid decay)
539
+ if (this.quantumChaosBlast > 0.01) {
540
+ hasActiveEffects = true;
541
+
542
+ const baseChaos = 0.3; // Quantum default chaos
543
+ const currentChaos = baseChaos + this.quantumChaosBlast;
544
+
545
+ if (window.updateParameter) {
546
+ window.updateParameter('chaos', Math.min(1.0, currentChaos).toFixed(2));
547
+ }
548
+
549
+ // Smooth decay
550
+ this.quantumChaosBlast *= 0.88; // Slightly faster than faceted for quantum energy feel
551
+ }
552
+
553
+ // DRAMATIC SPEED WAVE EFFECT (fluid decay)
554
+ if (this.quantumSpeedWave > 0.01) {
555
+ hasActiveEffects = true;
556
+
557
+ const baseSpeed = 1.0; // Quantum default speed
558
+ const currentSpeed = baseSpeed + this.quantumSpeedWave;
559
+
560
+ if (window.updateParameter) {
561
+ window.updateParameter('speed', Math.min(3.0, currentSpeed).toFixed(2));
562
+ }
563
+
564
+ // Smooth wave decay
565
+ this.quantumSpeedWave *= 0.89;
566
+ }
567
+
568
+ // QUANTUM HUE EXPLOSION EFFECT (fluid decay)
569
+ if (this.quantumHueShift > 1) {
570
+ hasActiveEffects = true;
571
+
572
+ const baseHue = 280; // Quantum purple-blue
573
+ const currentHue = (baseHue + this.quantumHueShift) % 360;
574
+
575
+ if (window.updateParameter) {
576
+ window.updateParameter('hue', Math.round(currentHue));
577
+ }
578
+
579
+ // Smooth color return
580
+ this.quantumHueShift *= 0.90;
581
+ }
582
+
583
+ if (this.isActive) {
584
+ requestAnimationFrame(quantumEffects);
585
+ }
586
+ };
587
+
588
+ quantumEffects();
589
+ }
590
+
591
+ async enableAudio() {
592
+ if (this.audioEnabled) return;
593
+
594
+ try {
595
+ // Request microphone access
596
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
597
+
598
+ // Create audio context and analyser
599
+ this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
600
+ this.analyser = this.audioContext.createAnalyser();
601
+
602
+ // Configure analyser for frequency analysis
603
+ this.analyser.fftSize = 256;
604
+ this.analyser.smoothingTimeConstant = 0.8;
605
+ this.frequencyData = new Uint8Array(this.analyser.frequencyBinCount);
606
+
607
+ // Store stream reference for cleanup
608
+ this._audioStream = stream;
609
+
610
+ // Connect microphone to analyser
611
+ const source = this.audioContext.createMediaStreamSource(stream);
612
+ source.connect(this.analyser);
613
+
614
+ this.audioEnabled = true;
615
+ console.log('Quantum audio reactivity enabled');
616
+
617
+ } catch (error) {
618
+ console.error('❌ Failed to enable Quantum audio:', error);
619
+ this.audioEnabled = false;
620
+ }
621
+ }
622
+
623
+ /**
624
+ * Update parameter across all quantum visualizers with enhanced integration
625
+ */
626
+ updateParameter(param, value) {
627
+ // Update internal parameter manager
628
+ this.parameters.setParameter(param, value);
629
+
630
+ // CRITICAL: Apply to all quantum visualizers with immediate render
631
+ this.visualizers.forEach(visualizer => {
632
+ if (visualizer.updateParameters) {
633
+ const params = {};
634
+ params[param] = value;
635
+ visualizer.updateParameters(params);
636
+ } else {
637
+ // Fallback: direct parameter update with manual render
638
+ if (visualizer.params) {
639
+ visualizer.params[param] = value;
640
+ if (visualizer.render) {
641
+ visualizer.render();
642
+ }
643
+ }
644
+ }
645
+ });
646
+
647
+ console.log(`🔮 Updated quantum ${param}: ${value}`);
648
+ }
649
+
650
+ /**
651
+ * Update multiple parameters
652
+ */
653
+ updateParameters(params) {
654
+ Object.keys(params).forEach(param => {
655
+ this.updateParameter(param, params[param]);
656
+ });
657
+ }
658
+
659
+ /**
660
+ * Update mouse interaction
661
+ */
662
+ updateInteraction(x, y, intensity) {
663
+ this.visualizers.forEach(visualizer => {
664
+ if (visualizer.updateInteraction) {
665
+ visualizer.updateInteraction(x, y, intensity);
666
+ }
667
+ });
668
+ }
669
+
670
+ /**
671
+ * Get current parameters for saving/export
672
+ */
673
+ getParameters() {
674
+ return this.parameters.getAllParameters();
675
+ }
676
+
677
+ /**
678
+ * Set parameters from loaded/imported data
679
+ */
680
+ setParameters(params) {
681
+ Object.keys(params).forEach(param => {
682
+ this.parameters.setParameter(param, params[param]);
683
+ });
684
+ this.updateParameters(params);
685
+ }
686
+
687
+ /**
688
+ * Start the render loop
689
+ */
690
+ startRenderLoop() {
691
+ if (window.mobileDebug) {
692
+ window.mobileDebug.log(`🎬 Quantum Engine: Starting render loop with ${this.visualizers?.length} visualizers, isActive=${this.isActive}`);
693
+ }
694
+
695
+ const render = () => {
696
+ this.renderFrame();
697
+
698
+ requestAnimationFrame(render);
699
+ };
700
+
701
+ render();
702
+ console.log('🎬 Quantum render loop started');
703
+
704
+ if (window.mobileDebug) {
705
+ window.mobileDebug.log(`✅ Quantum Engine: Render loop started, will render when isActive=true`);
706
+ }
707
+ }
708
+
709
+ /**
710
+ * Render a single frame.
711
+ * Dispatches to bridge mode or direct mode based on current _renderMode.
712
+ */
713
+ renderFrame() {
714
+ if (this.isActive) {
715
+ if (this._renderMode === 'bridge') {
716
+ this._renderBridgeFrame();
717
+ } else {
718
+ this._renderDirectFrame();
719
+ }
720
+
721
+ // Mobile debug: Log render activity periodically
722
+ if (window.mobileDebug && !this._renderActivityLogged) {
723
+ window.mobileDebug.log(`🎬 Quantum Engine: Actively rendering (${this._renderMode} mode)`);
724
+ this._renderActivityLogged = true;
725
+ }
726
+ } else if (window.mobileDebug && !this._inactiveWarningLogged) {
727
+ window.mobileDebug.log(`⚠️ Quantum Engine: Not rendering because isActive=false`);
728
+ this._inactiveWarningLogged = true;
729
+ }
730
+ }
731
+
732
+ /**
733
+ * Render a single frame using direct WebGL visualizers (original path).
734
+ * @private
735
+ */
736
+ _renderDirectFrame() {
737
+ const currentParams = this.parameters.getAllParameters();
738
+
739
+ this.visualizers.forEach(visualizer => {
740
+ if (visualizer.updateParameters && visualizer.render) {
741
+ visualizer.updateParameters(currentParams);
742
+ visualizer.render();
743
+ }
744
+ });
745
+ }
746
+
747
+ /**
748
+ * Update audio reactivity (for universal reactivity system)
749
+ */
750
+ // Audio reactivity now handled directly in visualizer render loops
751
+
752
+ /**
753
+ * Update click effects (for universal reactivity system)
754
+ */
755
+ updateClick(intensity) {
756
+ this.visualizers.forEach(visualizer => {
757
+ if (visualizer.triggerClick) {
758
+ visualizer.triggerClick(0.5, 0.5, intensity); // Click at center with intensity
759
+ }
760
+ });
761
+ }
762
+
763
+ /**
764
+ * Update scroll effects (for universal reactivity system)
765
+ */
766
+ updateScroll(velocity) {
767
+ this.visualizers.forEach(visualizer => {
768
+ if (visualizer.updateScroll) {
769
+ visualizer.updateScroll(velocity);
770
+ }
771
+ });
772
+ }
773
+
774
+ /**
775
+ * Clean up resources
776
+ */
777
+ destroy() {
778
+ this.isActive = false;
779
+
780
+ // Disconnect from universal reactivity
781
+ if (window.universalReactivity) {
782
+ window.universalReactivity.disconnectSystem('quantum');
783
+ }
784
+
785
+ // Stop audio stream tracks to release microphone
786
+ if (this._audioStream) {
787
+ this._audioStream.getTracks().forEach(track => track.stop());
788
+ this._audioStream = null;
789
+ }
790
+
791
+ // Close audio context
792
+ if (this.audioContext) {
793
+ this.audioContext.close().catch(() => {});
794
+ this.audioContext = null;
795
+ }
796
+ this.audioEnabled = false;
797
+ this.analyser = null;
798
+ this.frequencyData = null;
799
+
800
+ // Dispose bridge if active
801
+ if (this._multiCanvasBridge) {
802
+ this._multiCanvasBridge.dispose();
803
+ this._multiCanvasBridge = null;
804
+ }
805
+ this._renderMode = 'direct';
806
+
807
+ // Destroy all visualizers
808
+ this.visualizers.forEach(visualizer => {
809
+ if (visualizer.destroy) {
810
+ visualizer.destroy();
811
+ }
812
+ });
813
+ this.visualizers = [];
814
+ console.log('Quantum Engine destroyed');
815
+ }
816
+
817
+ // ============================================
818
+ // RendererContract Compliance Methods
819
+ // ============================================
820
+
821
+ /**
822
+ * Initialize or re-initialize with optional canvas override (RendererContract.init).
823
+ * Accepts the same context shape as FacetedSystem for consistency:
824
+ * { canvas: HTMLCanvasElement } or { canvasId: 'my-canvas' }
825
+ *
826
+ * @param {Object} [context]
827
+ * @param {HTMLCanvasElement} [context.canvas] - Canvas element override
828
+ * @param {string} [context.canvasId] - Canvas ID to look up
829
+ * @param {boolean} [context.preferWebGPU] - Try WebGPU bridge
830
+ * @returns {Promise<boolean>|boolean} Success status
831
+ */
832
+ initWithCanvas(context = {}) {
833
+ const canvasEl = context.canvas ||
834
+ (context.canvasId ? document.getElementById(context.canvasId) : null);
835
+
836
+ if (canvasEl) {
837
+ this.canvasOverride = canvasEl;
838
+ }
839
+
840
+ // Tear down any existing visualizers before re-init
841
+ this.visualizers.forEach(v => v.destroy && v.destroy());
842
+ this.visualizers = [];
843
+
844
+ this.createVisualizers();
845
+
846
+ if (!this.autoStart) return this.visualizers.length > 0;
847
+ this.startRenderLoop();
848
+ return this.visualizers.length > 0;
849
+ }
850
+
851
+ /**
852
+ * Handle canvas resize (RendererContract.resize)
853
+ * @param {number} width - New width in pixels
854
+ * @param {number} height - New height in pixels
855
+ * @param {number} [pixelRatio=1] - Device pixel ratio
856
+ */
857
+ resize(width, height, pixelRatio = 1) {
858
+ if (this._renderMode === 'bridge' && this._multiCanvasBridge) {
859
+ this._multiCanvasBridge.resizeAll(width, height, pixelRatio);
860
+ } else {
861
+ this.visualizers.forEach(visualizer => {
862
+ if (visualizer.canvas && visualizer.gl) {
863
+ visualizer.canvas.width = width * pixelRatio;
864
+ visualizer.canvas.height = height * pixelRatio;
865
+ visualizer.canvas.style.width = `${width}px`;
866
+ visualizer.canvas.style.height = `${height}px`;
867
+ visualizer.gl.viewport(0, 0, visualizer.canvas.width, visualizer.canvas.height);
868
+ }
869
+ });
870
+ }
871
+ console.log(`🔮 Quantum resized to ${width}x${height} @${pixelRatio}x`);
872
+ }
873
+
874
+ /**
875
+ * Render a single frame (RendererContract.render)
876
+ * @param {Object} [frameState] - Frame state with time, params, audio
877
+ */
878
+ render(frameState = {}) {
879
+ // Apply frameState parameters if provided
880
+ if (frameState.params) {
881
+ this.updateParameters(frameState.params);
882
+ }
883
+
884
+ // Delegate to existing renderFrame
885
+ this.renderFrame();
886
+ }
887
+
888
+ /**
889
+ * Get the current rendering backend type.
890
+ * @returns {'direct-webgl'|string}
891
+ */
892
+ getBackendType() {
893
+ if (this._renderMode === 'bridge' && this._multiCanvasBridge) {
894
+ return this._multiCanvasBridge.backendType || 'bridge';
895
+ }
896
+ return 'direct-webgl';
897
+ }
898
+
899
+ /**
900
+ * Clean up all resources (RendererContract.dispose)
901
+ * Alias for destroy() for contract compliance
902
+ */
903
+ dispose() {
904
+ this.destroy();
905
+ }
906
+ }