@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,374 @@
1
+ /**
2
+ * ViewerPortal.js - Immersive Fullscreen 4D Visualization Viewer
3
+ *
4
+ * Provides an immersive viewing experience with:
5
+ * - Fullscreen mode with escape handling
6
+ * - Device orientation (gyroscope) control
7
+ * - Touch/mouse gesture rotation
8
+ * - Card bending 3D effect
9
+ * - Screenshot and trading card export
10
+ */
11
+
12
+ import { EventEmitter } from 'events';
13
+
14
+ /**
15
+ * Viewer display modes
16
+ */
17
+ export const ViewerMode = {
18
+ NORMAL: 'normal',
19
+ FULLSCREEN: 'fullscreen',
20
+ IMMERSIVE: 'immersive',
21
+ CARD: 'card'
22
+ };
23
+
24
+ /**
25
+ * Projection modes for 4D viewing
26
+ */
27
+ export const ProjectionMode = {
28
+ PERSPECTIVE: 'perspective',
29
+ STEREOGRAPHIC: 'stereographic',
30
+ ORTHOGRAPHIC: 'orthographic',
31
+ CROSS_SECTION: 'cross_section'
32
+ };
33
+
34
+ /**
35
+ * ViewerPortal - Immersive 4D Visualization Viewer
36
+ */
37
+ export class ViewerPortal extends EventEmitter {
38
+ constructor(options = {}) {
39
+ super();
40
+
41
+ this.container = null;
42
+ this.canvas = null;
43
+ this.engine = null;
44
+ this.mode = ViewerMode.NORMAL;
45
+ this.projectionMode = ProjectionMode.PERSPECTIVE;
46
+ this.isFullscreen = false;
47
+ this.gyroscopeEnabled = false;
48
+
49
+ this.rotation = { xy: 0, xz: 0, yz: 0, xw: 0, yw: 0, zw: 0 };
50
+ this.velocity = { xy: 0, xz: 0, yz: 0, xw: 0, yw: 0, zw: 0 };
51
+
52
+ this.damping = options.damping || 0.95;
53
+ this.sensitivity = options.sensitivity || 0.01;
54
+ this.autoRotate = options.autoRotate || false;
55
+ this.autoRotateSpeed = options.autoRotateSpeed || 0.005;
56
+ this.autoRotatePlanes = options.autoRotatePlanes || ['xw', 'yw'];
57
+ this.cardBend = { x: 0, y: 0 };
58
+
59
+ this._animationFrame = null;
60
+ this._touch = { active: false, startX: 0, startY: 0, lastX: 0, lastY: 0 };
61
+ this._deviceOrientation = { alpha: 0, beta: 0, gamma: 0 };
62
+
63
+ this._onResize = this._onResize.bind(this);
64
+ this._onKeyDown = this._onKeyDown.bind(this);
65
+ this._onMouseDown = this._onMouseDown.bind(this);
66
+ this._onMouseMove = this._onMouseMove.bind(this);
67
+ this._onMouseUp = this._onMouseUp.bind(this);
68
+ this._onTouchStart = this._onTouchStart.bind(this);
69
+ this._onTouchMove = this._onTouchMove.bind(this);
70
+ this._onTouchEnd = this._onTouchEnd.bind(this);
71
+ this._onDeviceOrientation = this._onDeviceOrientation.bind(this);
72
+ this._onFullscreenChange = this._onFullscreenChange.bind(this);
73
+ this._animate = this._animate.bind(this);
74
+ }
75
+
76
+ initialize(container, engine) {
77
+ this.container = container;
78
+ this.engine = engine;
79
+
80
+ this.canvas = container.querySelector('canvas');
81
+ if (!this.canvas) {
82
+ this.canvas = document.createElement('canvas');
83
+ this.canvas.style.width = '100%';
84
+ this.canvas.style.height = '100%';
85
+ container.appendChild(this.canvas);
86
+ }
87
+
88
+ this._applyStyles();
89
+ this._addEventListeners();
90
+ this._startAnimation();
91
+ this.emit('initialized');
92
+ return this;
93
+ }
94
+
95
+ dispose() {
96
+ this._stopAnimation();
97
+ this._removeEventListeners();
98
+ this.emit('disposed');
99
+ }
100
+
101
+ async enterFullscreen() {
102
+ if (!this.container) return;
103
+ try {
104
+ await (this.container.requestFullscreen?.() ||
105
+ this.container.webkitRequestFullscreen?.() ||
106
+ this.container.mozRequestFullScreen?.());
107
+ this.isFullscreen = true;
108
+ this.mode = ViewerMode.FULLSCREEN;
109
+ this.emit('fullscreen', true);
110
+ } catch (err) {
111
+ console.warn('Fullscreen not available:', err);
112
+ }
113
+ }
114
+
115
+ async exitFullscreen() {
116
+ try {
117
+ await (document.exitFullscreen?.() ||
118
+ document.webkitExitFullscreen?.() ||
119
+ document.mozCancelFullScreen?.());
120
+ this.isFullscreen = false;
121
+ this.mode = ViewerMode.NORMAL;
122
+ this.emit('fullscreen', false);
123
+ } catch (err) {
124
+ console.warn('Exit fullscreen failed:', err);
125
+ }
126
+ }
127
+
128
+ toggleFullscreen() {
129
+ this.isFullscreen ? this.exitFullscreen() : this.enterFullscreen();
130
+ }
131
+
132
+ async enterImmersiveMode() {
133
+ await this.enterFullscreen();
134
+ await this.enableGyroscope();
135
+ this.mode = ViewerMode.IMMERSIVE;
136
+ this.emit('immersive', true);
137
+ }
138
+
139
+ async enableGyroscope() {
140
+ if (typeof DeviceOrientationEvent !== 'undefined' &&
141
+ typeof DeviceOrientationEvent.requestPermission === 'function') {
142
+ try {
143
+ const permission = await DeviceOrientationEvent.requestPermission();
144
+ if (permission !== 'granted') return false;
145
+ } catch (err) {
146
+ console.warn('Gyroscope permission denied:', err);
147
+ return false;
148
+ }
149
+ }
150
+ window.addEventListener('deviceorientation', this._onDeviceOrientation);
151
+ this.gyroscopeEnabled = true;
152
+ this.emit('gyroscope', true);
153
+ return true;
154
+ }
155
+
156
+ disableGyroscope() {
157
+ window.removeEventListener('deviceorientation', this._onDeviceOrientation);
158
+ this.gyroscopeEnabled = false;
159
+ this.emit('gyroscope', false);
160
+ }
161
+
162
+ setRotation(plane, angle) {
163
+ if (this.rotation.hasOwnProperty(plane)) {
164
+ this.rotation[plane] = angle;
165
+ this._updateEngine();
166
+ }
167
+ }
168
+
169
+ setAllRotations(rotations) {
170
+ Object.assign(this.rotation, rotations);
171
+ this._updateEngine();
172
+ }
173
+
174
+ resetRotation() {
175
+ this.rotation = { xy: 0, xz: 0, yz: 0, xw: 0, yw: 0, zw: 0 };
176
+ this.velocity = { xy: 0, xz: 0, yz: 0, xw: 0, yw: 0, zw: 0 };
177
+ this._updateEngine();
178
+ this.emit('reset');
179
+ }
180
+
181
+ setProjectionMode(mode) {
182
+ this.projectionMode = mode;
183
+ this.emit('projectionMode', mode);
184
+ }
185
+
186
+ captureFrame(format = 'png', quality = 0.92) {
187
+ if (!this.canvas) return null;
188
+ return this.canvas.toDataURL(\`image/\${format}\`, quality);
189
+ }
190
+
191
+ downloadFrame(filename = 'vib3-capture', format = 'png') {
192
+ const dataUrl = this.captureFrame(format);
193
+ if (!dataUrl) return;
194
+ const link = document.createElement('a');
195
+ link.download = \`\${filename}.\${format}\`;
196
+ link.href = dataUrl;
197
+ link.click();
198
+ }
199
+
200
+ _applyStyles() {
201
+ if (!this.container) return;
202
+ Object.assign(this.container.style, {
203
+ position: 'relative', overflow: 'hidden',
204
+ touchAction: 'none', userSelect: 'none', webkitUserSelect: 'none'
205
+ });
206
+ if (this.canvas) {
207
+ Object.assign(this.canvas.style, { display: 'block', width: '100%', height: '100%' });
208
+ }
209
+ }
210
+
211
+ _addEventListeners() {
212
+ window.addEventListener('resize', this._onResize);
213
+ document.addEventListener('keydown', this._onKeyDown);
214
+ document.addEventListener('fullscreenchange', this._onFullscreenChange);
215
+ document.addEventListener('webkitfullscreenchange', this._onFullscreenChange);
216
+ if (this.container) {
217
+ this.container.addEventListener('mousedown', this._onMouseDown);
218
+ this.container.addEventListener('touchstart', this._onTouchStart, { passive: false });
219
+ }
220
+ }
221
+
222
+ _removeEventListeners() {
223
+ window.removeEventListener('resize', this._onResize);
224
+ document.removeEventListener('keydown', this._onKeyDown);
225
+ document.removeEventListener('fullscreenchange', this._onFullscreenChange);
226
+ document.removeEventListener('webkitfullscreenchange', this._onFullscreenChange);
227
+ document.removeEventListener('mousemove', this._onMouseMove);
228
+ document.removeEventListener('mouseup', this._onMouseUp);
229
+ document.removeEventListener('touchmove', this._onTouchMove);
230
+ document.removeEventListener('touchend', this._onTouchEnd);
231
+ if (this.container) {
232
+ this.container.removeEventListener('mousedown', this._onMouseDown);
233
+ this.container.removeEventListener('touchstart', this._onTouchStart);
234
+ }
235
+ this.disableGyroscope();
236
+ }
237
+
238
+ _onResize() {
239
+ if (this.canvas && this.container) {
240
+ const rect = this.container.getBoundingClientRect();
241
+ this.canvas.width = rect.width * window.devicePixelRatio;
242
+ this.canvas.height = rect.height * window.devicePixelRatio;
243
+ }
244
+ this.emit('resize');
245
+ }
246
+
247
+ _onKeyDown(event) {
248
+ switch (event.key) {
249
+ case 'Escape': if (this.isFullscreen) this.exitFullscreen(); break;
250
+ case 'f': case 'F': this.toggleFullscreen(); break;
251
+ case 'r': case 'R': this.resetRotation(); break;
252
+ case 's': case 'S':
253
+ if (event.ctrlKey || event.metaKey) { event.preventDefault(); this.downloadFrame(); }
254
+ break;
255
+ case ' ': this.autoRotate = !this.autoRotate; this.emit('autoRotate', this.autoRotate); break;
256
+ }
257
+ }
258
+
259
+ _onMouseDown(event) {
260
+ this._touch.active = true;
261
+ this._touch.startX = this._touch.lastX = event.clientX;
262
+ this._touch.startY = this._touch.lastY = event.clientY;
263
+ document.addEventListener('mousemove', this._onMouseMove);
264
+ document.addEventListener('mouseup', this._onMouseUp);
265
+ this.emit('interactionStart');
266
+ }
267
+
268
+ _onMouseMove(event) {
269
+ if (!this._touch.active) return;
270
+ const deltaX = event.clientX - this._touch.lastX;
271
+ const deltaY = event.clientY - this._touch.lastY;
272
+ this._touch.lastX = event.clientX;
273
+ this._touch.lastY = event.clientY;
274
+ this.velocity.xw += deltaX * this.sensitivity;
275
+ this.velocity.yw += deltaY * this.sensitivity;
276
+ this.cardBend.x = (event.clientX - this._touch.startX) * 0.1;
277
+ this.cardBend.y = (event.clientY - this._touch.startY) * 0.1;
278
+ this.emit('interaction', { deltaX, deltaY });
279
+ }
280
+
281
+ _onMouseUp() {
282
+ this._touch.active = false;
283
+ this.cardBend = { x: 0, y: 0 };
284
+ document.removeEventListener('mousemove', this._onMouseMove);
285
+ document.removeEventListener('mouseup', this._onMouseUp);
286
+ this.emit('interactionEnd');
287
+ }
288
+
289
+ _onTouchStart(event) {
290
+ event.preventDefault();
291
+ const touch = event.touches[0];
292
+ this._touch.active = true;
293
+ this._touch.startX = this._touch.lastX = touch.clientX;
294
+ this._touch.startY = this._touch.lastY = touch.clientY;
295
+ document.addEventListener('touchmove', this._onTouchMove, { passive: false });
296
+ document.addEventListener('touchend', this._onTouchEnd);
297
+ this.emit('interactionStart');
298
+ }
299
+
300
+ _onTouchMove(event) {
301
+ event.preventDefault();
302
+ if (!this._touch.active) return;
303
+ const touch = event.touches[0];
304
+ const deltaX = touch.clientX - this._touch.lastX;
305
+ const deltaY = touch.clientY - this._touch.lastY;
306
+ this._touch.lastX = touch.clientX;
307
+ this._touch.lastY = touch.clientY;
308
+ this.velocity.xw += deltaX * this.sensitivity;
309
+ this.velocity.yw += deltaY * this.sensitivity;
310
+ this.cardBend.x = (touch.clientX - this._touch.startX) * 0.1;
311
+ this.cardBend.y = (touch.clientY - this._touch.startY) * 0.1;
312
+ this.emit('interaction', { deltaX, deltaY });
313
+ }
314
+
315
+ _onTouchEnd() {
316
+ this._touch.active = false;
317
+ this.cardBend = { x: 0, y: 0 };
318
+ document.removeEventListener('touchmove', this._onTouchMove);
319
+ document.removeEventListener('touchend', this._onTouchEnd);
320
+ this.emit('interactionEnd');
321
+ }
322
+
323
+ _onDeviceOrientation(event) {
324
+ const { alpha, beta, gamma } = event;
325
+ const alphaRad = (alpha || 0) * Math.PI / 180;
326
+ const betaRad = (beta || 0) * Math.PI / 180;
327
+ const gammaRad = (gamma || 0) * Math.PI / 180;
328
+ const smooth = 0.1;
329
+ this.rotation.zw += (alphaRad * 0.5 - this.rotation.zw) * smooth;
330
+ this.rotation.yw += (betaRad * 0.3 - this.rotation.yw) * smooth;
331
+ this.rotation.xw += (gammaRad * 0.3 - this.rotation.xw) * smooth;
332
+ this._deviceOrientation = { alpha, beta, gamma };
333
+ this.emit('deviceOrientation', this._deviceOrientation);
334
+ }
335
+
336
+ _onFullscreenChange() {
337
+ this.isFullscreen = !!document.fullscreenElement || !!document.webkitFullscreenElement;
338
+ if (!this.isFullscreen) {
339
+ this.mode = ViewerMode.NORMAL;
340
+ this.emit('fullscreen', false);
341
+ }
342
+ }
343
+
344
+ _startAnimation() { this._animate(); }
345
+
346
+ _stopAnimation() {
347
+ if (this._animationFrame) {
348
+ cancelAnimationFrame(this._animationFrame);
349
+ this._animationFrame = null;
350
+ }
351
+ }
352
+
353
+ _animate() {
354
+ for (const plane of Object.keys(this.velocity)) {
355
+ this.rotation[plane] += this.velocity[plane];
356
+ this.velocity[plane] *= this.damping;
357
+ if (Math.abs(this.velocity[plane]) < 0.0001) this.velocity[plane] = 0;
358
+ }
359
+ if (this.autoRotate && !this._touch.active) {
360
+ for (const plane of this.autoRotatePlanes) {
361
+ this.rotation[plane] += this.autoRotateSpeed;
362
+ }
363
+ }
364
+ this._updateEngine();
365
+ this._animationFrame = requestAnimationFrame(this._animate);
366
+ }
367
+
368
+ _updateEngine() {
369
+ if (this.engine?.setRotation) this.engine.setRotation(this.rotation);
370
+ this.emit('update', this.rotation);
371
+ }
372
+ }
373
+
374
+ export default ViewerPortal;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * VIB3+ Viewer Module Index
3
+ *
4
+ * Exports all viewer components for immersive 4D visualization
5
+ */
6
+
7
+ export { ViewerPortal, ViewerMode, ProjectionMode } from './ViewerPortal.js';
8
+ export { ReactivityManager } from './ReactivityManager.js';
9
+ export { CardBending, BendPreset } from './CardBending.js';
10
+ export { TradingCardExporter, CardSize, FrameStyle, Rarity } from './TradingCardExporter.js';
11
+ export { AudioReactivity, AudioSource, FrequencyBand } from './AudioReactivity.js';
12
+ export { GalleryUI, ViewMode, SortBy } from './GalleryUI.js';
@@ -0,0 +1,296 @@
1
+ /**
2
+ * WasmLoader.js - WebAssembly Module Loader with JavaScript Fallback
3
+ *
4
+ * Loads the VIB3+ WASM module when available, otherwise falls back
5
+ * to pure JavaScript implementations.
6
+ */
7
+
8
+ // Import JavaScript fallbacks
9
+ import { Vec4 as JsVec4 } from '../math/Vec4.js';
10
+ import { Rotor4D as JsRotor4D } from '../math/Rotor4D.js';
11
+ import { Mat4x4 as JsMat4x4 } from '../math/Mat4x4.js';
12
+ import * as JsProjection from '../math/Projection.js';
13
+
14
+ /**
15
+ * Module state
16
+ */
17
+ let wasmModule = null;
18
+ let isLoaded = false;
19
+ let isLoading = false;
20
+ let loadError = null;
21
+ let useWasm = false;
22
+
23
+ /**
24
+ * Configuration options
25
+ */
26
+ const config = {
27
+ /** Path to WASM files */
28
+ wasmPath: '/wasm/',
29
+ /** Prefer WASM over JavaScript when available */
30
+ preferWasm: true,
31
+ /** Timeout for WASM loading (ms) */
32
+ loadTimeout: 10000,
33
+ /** Enable debug logging */
34
+ debug: false
35
+ };
36
+
37
+ /**
38
+ * Set configuration options
39
+ * @param {object} options
40
+ */
41
+ export function configure(options) {
42
+ Object.assign(config, options);
43
+ }
44
+
45
+ /**
46
+ * Log debug message
47
+ * @private
48
+ */
49
+ function debugLog(...args) {
50
+ if (config.debug) {
51
+ console.log('[VIB3-WASM]', ...args);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Check if WebAssembly is supported
57
+ * @returns {boolean}
58
+ */
59
+ export function isWasmSupported() {
60
+ return typeof WebAssembly !== 'undefined' &&
61
+ typeof WebAssembly.instantiate === 'function';
62
+ }
63
+
64
+ /**
65
+ * Check if SIMD is supported in WebAssembly
66
+ * @returns {boolean}
67
+ */
68
+ export function isSimdSupported() {
69
+ if (!isWasmSupported()) return false;
70
+
71
+ try {
72
+ // Test SIMD support with a minimal WASM module
73
+ const simdTest = new Uint8Array([
74
+ 0x00, 0x61, 0x73, 0x6d, // WASM magic
75
+ 0x01, 0x00, 0x00, 0x00, // Version 1
76
+ 0x01, 0x05, 0x01, 0x60, 0x00, 0x01, 0x7b, // Type section (v128 return)
77
+ 0x03, 0x02, 0x01, 0x00, // Function section
78
+ 0x0a, 0x0a, 0x01, 0x08, 0x00, 0xfd, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0b // Code section
79
+ ]);
80
+ return WebAssembly.validate(simdTest);
81
+ } catch {
82
+ return false;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Load the WASM module
88
+ * @returns {Promise<object>} The loaded module or fallback
89
+ */
90
+ export async function loadWasmModule() {
91
+ if (isLoaded) {
92
+ return wasmModule;
93
+ }
94
+
95
+ if (isLoading) {
96
+ // Wait for existing load to complete
97
+ return new Promise((resolve, reject) => {
98
+ const checkInterval = setInterval(() => {
99
+ if (isLoaded) {
100
+ clearInterval(checkInterval);
101
+ resolve(wasmModule);
102
+ } else if (loadError) {
103
+ clearInterval(checkInterval);
104
+ reject(loadError);
105
+ }
106
+ }, 50);
107
+ });
108
+ }
109
+
110
+ if (!config.preferWasm || !isWasmSupported()) {
111
+ debugLog('Using JavaScript fallback (WASM not preferred or unsupported)');
112
+ return getFallbackModule();
113
+ }
114
+
115
+ isLoading = true;
116
+
117
+ try {
118
+ debugLog('Loading WASM module...');
119
+
120
+ // Dynamic import of the WASM module
121
+ const wasmPath = config.wasmPath.endsWith('/') ? config.wasmPath : config.wasmPath + '/';
122
+ const moduleUrl = wasmPath + 'vib3.js';
123
+
124
+ // Create abort controller for timeout
125
+ const controller = new AbortController();
126
+ const timeoutId = setTimeout(() => controller.abort(), config.loadTimeout);
127
+
128
+ try {
129
+ // Try to load the WASM module factory
130
+ const createModule = await import(/* webpackIgnore: true */ moduleUrl);
131
+
132
+ clearTimeout(timeoutId);
133
+
134
+ // Initialize the module
135
+ wasmModule = await createModule.default({
136
+ locateFile: (path) => wasmPath + path
137
+ });
138
+
139
+ isLoaded = true;
140
+ useWasm = true;
141
+ debugLog('WASM module loaded successfully');
142
+ debugLog('SIMD enabled:', wasmModule.hasSimd?.() ?? 'unknown');
143
+
144
+ return wasmModule;
145
+
146
+ } catch (err) {
147
+ clearTimeout(timeoutId);
148
+ throw err;
149
+ }
150
+
151
+ } catch (err) {
152
+ debugLog('WASM loading failed, using fallback:', err.message);
153
+ loadError = err;
154
+ return getFallbackModule();
155
+
156
+ } finally {
157
+ isLoading = false;
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Get the fallback JavaScript module
163
+ * @private
164
+ */
165
+ function getFallbackModule() {
166
+ wasmModule = createFallbackModule();
167
+ isLoaded = true;
168
+ useWasm = false;
169
+ return wasmModule;
170
+ }
171
+
172
+ /**
173
+ * Create fallback module wrapping JavaScript implementations
174
+ * @private
175
+ */
176
+ function createFallbackModule() {
177
+ return {
178
+ // Version info
179
+ getVersion: () => '1.0.0-js',
180
+ hasSimd: () => false,
181
+ isWasm: () => false,
182
+
183
+ // Vec4
184
+ Vec4: JsVec4,
185
+ vec4FromArray: (arr) => new JsVec4(arr[0], arr[1], arr[2], arr[3]),
186
+
187
+ // Rotor4D
188
+ Rotor4D: JsRotor4D,
189
+ RotationPlane: {
190
+ XY: 0, XZ: 1, YZ: 2, XW: 3, YW: 4, ZW: 5
191
+ },
192
+ rotorFromEuler6Array: (arr) => JsRotor4D.fromEuler6(
193
+ arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]
194
+ ),
195
+
196
+ // Mat4x4
197
+ Mat4x4: JsMat4x4,
198
+ matrixFromAnglesArray: (arr) => JsMat4x4.rotationFromAngles(
199
+ arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]
200
+ ),
201
+
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
209
+ };
210
+ }
211
+
212
+ /**
213
+ * Check if WASM module is loaded
214
+ * @returns {boolean}
215
+ */
216
+ export function isWasmLoaded() {
217
+ return isLoaded && useWasm;
218
+ }
219
+
220
+ /**
221
+ * Check if fallback is being used
222
+ * @returns {boolean}
223
+ */
224
+ export function isFallbackActive() {
225
+ return isLoaded && !useWasm;
226
+ }
227
+
228
+ /**
229
+ * Get the current module (WASM or fallback)
230
+ * @returns {object|null}
231
+ */
232
+ export function getModule() {
233
+ return wasmModule;
234
+ }
235
+
236
+ /**
237
+ * Get module status
238
+ * @returns {object}
239
+ */
240
+ export function getStatus() {
241
+ return {
242
+ isLoaded,
243
+ isLoading,
244
+ useWasm,
245
+ hasError: loadError !== null,
246
+ error: loadError?.message ?? null,
247
+ simdSupported: isSimdSupported(),
248
+ wasmSupported: isWasmSupported()
249
+ };
250
+ }
251
+
252
+ /**
253
+ * Force reload the module (for testing)
254
+ */
255
+ export function reset() {
256
+ wasmModule = null;
257
+ isLoaded = false;
258
+ isLoading = false;
259
+ loadError = null;
260
+ useWasm = false;
261
+ }
262
+
263
+ /**
264
+ * Auto-initialize on import if in browser
265
+ */
266
+ let initPromise = null;
267
+
268
+ export function init() {
269
+ if (!initPromise) {
270
+ initPromise = loadWasmModule().catch(err => {
271
+ debugLog('Auto-init failed:', err.message);
272
+ return getFallbackModule();
273
+ });
274
+ }
275
+ return initPromise;
276
+ }
277
+
278
+ // Convenience re-exports
279
+ export {
280
+ JsVec4 as Vec4Fallback,
281
+ JsRotor4D as Rotor4DFallback,
282
+ JsMat4x4 as Mat4x4Fallback
283
+ };
284
+
285
+ export default {
286
+ configure,
287
+ loadWasmModule,
288
+ isWasmSupported,
289
+ isSimdSupported,
290
+ isWasmLoaded,
291
+ isFallbackActive,
292
+ getModule,
293
+ getStatus,
294
+ reset,
295
+ init
296
+ };