@vib3code/sdk 2.0.1 → 2.0.3-canary.0a63e71

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 (192) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +245 -0
  3. package/DOCS/ANDROID_DEPLOYMENT.md +59 -0
  4. package/DOCS/ARCHITECTURE.md +1 -0
  5. package/DOCS/CI_TESTING.md +2 -0
  6. package/DOCS/CLI_ONBOARDING.md +3 -1
  7. package/DOCS/CONTROL_REFERENCE.md +2 -0
  8. package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +119 -0
  9. package/DOCS/ENV_SETUP.md +2 -0
  10. package/DOCS/EPIC_SCROLL_EVENTS.md +775 -0
  11. package/DOCS/EXPANSION_DESIGN.md +979 -0
  12. package/DOCS/EXPANSION_DESIGN_ULTRA.md +389 -0
  13. package/DOCS/EXPORT_FORMATS.md +2 -0
  14. package/DOCS/GPU_DISPOSAL_GUIDE.md +2 -0
  15. package/DOCS/HANDOFF_LANDING_PAGE.md +156 -0
  16. package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +495 -0
  17. package/DOCS/LICENSING_TIERS.md +2 -0
  18. package/DOCS/MASTER_PLAN_2026-01-31.md +4 -2
  19. package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +939 -0
  20. package/DOCS/OBS_SETUP_GUIDE.md +2 -0
  21. package/DOCS/OPTIMIZATION_PLAN_MATH.md +119 -0
  22. package/DOCS/PRODUCT_STRATEGY.md +65 -0
  23. package/DOCS/PROJECT_SETUP.md +2 -0
  24. package/DOCS/README.md +105 -0
  25. package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +99 -0
  26. package/DOCS/RENDERER_LIFECYCLE.md +2 -0
  27. package/DOCS/REPO_MANIFEST.md +2 -0
  28. package/DOCS/ROADMAP.md +113 -0
  29. package/DOCS/SCROLL_TIMELINE_v3.md +271 -0
  30. package/DOCS/SITE_REFACTOR_PLAN.md +102 -0
  31. package/DOCS/STATUS.md +26 -0
  32. package/DOCS/SYSTEM_INVENTORY.md +37 -32
  33. package/DOCS/TELEMETRY_EXPORTS.md +2 -0
  34. package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +87 -0
  35. package/DOCS/VISUAL_ANALYSIS_FACETAD.md +135 -0
  36. package/DOCS/VISUAL_ANALYSIS_SIMONE.md +97 -0
  37. package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +88 -0
  38. package/DOCS/WEBGPU_STATUS.md +121 -38
  39. package/DOCS/XR_BENCHMARKS.md +2 -0
  40. package/DOCS/archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +1 -0
  41. package/DOCS/archive/DEV_TRACK_ANALYSIS.md +1 -0
  42. package/DOCS/archive/DEV_TRACK_PLAN_2026-01-07.md +1 -0
  43. package/DOCS/archive/SESSION_014_PLAN.md +1 -0
  44. package/DOCS/archive/SESSION_LOG_2026-01-07.md +1 -0
  45. package/DOCS/archive/STRATEGIC_BLUEPRINT_2026-01-07.md +1 -0
  46. package/DOCS/archive/SYSTEM_AUDIT_2026-01-30.md +1 -0
  47. package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +1 -0
  48. package/DOCS/{DEV_TRACK_SESSION_2026-01-31.md → dev-tracks/DEV_TRACK_SESSION_2026-01-31.md} +3 -1
  49. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +233 -0
  50. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +129 -0
  51. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +144 -0
  52. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +110 -0
  53. package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +310 -0
  54. package/DOCS/dev-tracks/README.md +12 -0
  55. package/README.md +26 -13
  56. package/cpp/CMakeLists.txt +236 -0
  57. package/cpp/bindings/embind.cpp +269 -0
  58. package/cpp/build.sh +129 -0
  59. package/cpp/geometry/Crystal.cpp +103 -0
  60. package/cpp/geometry/Fractal.cpp +136 -0
  61. package/cpp/geometry/GeometryGenerator.cpp +262 -0
  62. package/cpp/geometry/KleinBottle.cpp +71 -0
  63. package/cpp/geometry/Sphere.cpp +134 -0
  64. package/cpp/geometry/Tesseract.cpp +94 -0
  65. package/cpp/geometry/Tetrahedron.cpp +83 -0
  66. package/cpp/geometry/Torus.cpp +65 -0
  67. package/cpp/geometry/WarpFunctions.cpp +238 -0
  68. package/cpp/geometry/Wave.cpp +85 -0
  69. package/cpp/include/vib3_ffi.h +238 -0
  70. package/cpp/math/Mat4x4.cpp +409 -0
  71. package/cpp/math/Mat4x4.hpp +209 -0
  72. package/cpp/math/Projection.cpp +142 -0
  73. package/cpp/math/Projection.hpp +148 -0
  74. package/cpp/math/Rotor4D.cpp +322 -0
  75. package/cpp/math/Rotor4D.hpp +204 -0
  76. package/cpp/math/Vec4.cpp +303 -0
  77. package/cpp/math/Vec4.hpp +225 -0
  78. package/cpp/src/vib3_ffi.cpp +607 -0
  79. package/cpp/tests/Geometry_test.cpp +213 -0
  80. package/cpp/tests/Mat4x4_test.cpp +494 -0
  81. package/cpp/tests/Projection_test.cpp +298 -0
  82. package/cpp/tests/Rotor4D_test.cpp +423 -0
  83. package/cpp/tests/Vec4_test.cpp +489 -0
  84. package/docs/webgpu-live.html +1 -1
  85. package/package.json +41 -30
  86. package/src/agent/index.js +1 -3
  87. package/src/agent/mcp/MCPServer.js +1220 -144
  88. package/src/agent/mcp/index.js +1 -1
  89. package/src/agent/mcp/stdio-server.js +264 -0
  90. package/src/agent/mcp/tools.js +498 -31
  91. package/src/cli/index.js +431 -47
  92. package/src/core/CanvasManager.js +97 -204
  93. package/src/core/ErrorReporter.js +1 -1
  94. package/src/core/Parameters.js +1 -1
  95. package/src/core/VIB3Engine.js +93 -4
  96. package/src/core/VitalitySystem.js +53 -0
  97. package/src/core/index.js +18 -0
  98. package/src/core/renderers/FacetedRendererAdapter.js +10 -9
  99. package/src/core/renderers/HolographicRendererAdapter.js +13 -9
  100. package/src/core/renderers/QuantumRendererAdapter.js +11 -7
  101. package/src/creative/AestheticMapper.js +628 -0
  102. package/src/creative/ChoreographyPlayer.js +481 -0
  103. package/src/creative/index.js +11 -0
  104. package/src/experimental/GameLoop.js +72 -0
  105. package/src/experimental/LatticePhysics.js +100 -0
  106. package/src/experimental/LiveDirector.js +143 -0
  107. package/src/experimental/PlayerController4D.js +154 -0
  108. package/src/experimental/VIB3Actor.js +138 -0
  109. package/src/experimental/VIB3Compositor.js +117 -0
  110. package/src/experimental/VIB3Link.js +122 -0
  111. package/src/experimental/VIB3Orchestrator.js +146 -0
  112. package/src/experimental/VIB3Universe.js +109 -0
  113. package/src/experimental/demos/CrystalLabyrinth.js +202 -0
  114. package/src/export/TradingCardManager.js +3 -4
  115. package/src/export/index.js +11 -1
  116. package/src/faceted/FacetedSystem.js +260 -394
  117. package/src/games/glyph-war/GlyphWarVisualizer.js +641 -0
  118. package/src/geometry/generators/Crystal.js +2 -2
  119. package/src/geometry/warp/HypersphereCore.js +53 -24
  120. package/src/holograms/HolographicVisualizer.js +84 -98
  121. package/src/holograms/RealHolographicSystem.js +194 -43
  122. package/src/math/Mat4x4.js +308 -105
  123. package/src/math/Rotor4D.js +124 -40
  124. package/src/math/Vec4.js +200 -103
  125. package/src/math/index.js +7 -7
  126. package/src/polychora/PolychoraSystem.js +77 -0
  127. package/src/quantum/QuantumEngine.js +103 -66
  128. package/src/quantum/QuantumVisualizer.js +31 -22
  129. package/src/reactivity/index.js +3 -5
  130. package/src/render/LayerPresetManager.js +372 -0
  131. package/src/render/LayerReactivityBridge.js +344 -0
  132. package/src/render/LayerRelationshipGraph.js +610 -0
  133. package/src/render/MultiCanvasBridge.js +148 -25
  134. package/src/render/ShaderLoader.js +38 -0
  135. package/src/render/ShaderProgram.js +4 -4
  136. package/src/render/UnifiedRenderBridge.js +4 -1
  137. package/src/render/backends/WebGPUBackend.js +8 -4
  138. package/src/render/index.js +27 -2
  139. package/src/scene/Node4D.js +74 -24
  140. package/src/scene/index.js +4 -4
  141. package/src/shaders/common/geometry24.glsl +65 -0
  142. package/src/shaders/common/geometry24.wgsl +54 -0
  143. package/src/shaders/common/rotation4d.glsl +4 -4
  144. package/src/shaders/common/rotation4d.wgsl +2 -2
  145. package/src/shaders/common/uniforms.wgsl +15 -8
  146. package/src/shaders/faceted/faceted.frag.glsl +220 -80
  147. package/src/shaders/faceted/faceted.frag.wgsl +144 -90
  148. package/src/shaders/holographic/holographic.frag.glsl +28 -9
  149. package/src/shaders/holographic/holographic.frag.wgsl +112 -41
  150. package/src/shaders/quantum/quantum.frag.glsl +1 -0
  151. package/src/shaders/quantum/quantum.frag.wgsl +6 -4
  152. package/src/testing/ParallelTestFramework.js +2 -2
  153. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +2 -2
  154. package/src/viewer/GalleryUI.js +17 -0
  155. package/src/viewer/ViewerPortal.js +2 -2
  156. package/src/viewer/index.js +1 -1
  157. package/tools/headless-renderer.js +258 -0
  158. package/tools/shader-sync-verify.js +14 -8
  159. package/tools/site-analysis/all-reports.json +32 -0
  160. package/tools/site-analysis/combined-analysis.md +50 -0
  161. package/tools/site-analyzer.mjs +779 -0
  162. package/tools/visual-catalog/capture.js +276 -0
  163. package/tools/visual-catalog/composite.js +138 -0
  164. package/types/adaptive-sdk.d.ts +204 -5
  165. package/types/agent/cli.d.ts +78 -0
  166. package/types/agent/index.d.ts +18 -0
  167. package/types/agent/mcp.d.ts +87 -0
  168. package/types/agent/telemetry.d.ts +190 -0
  169. package/types/core/VIB3Engine.d.ts +26 -0
  170. package/types/core/index.d.ts +261 -0
  171. package/types/creative/AestheticMapper.d.ts +72 -0
  172. package/types/creative/ChoreographyPlayer.d.ts +96 -0
  173. package/types/creative/index.d.ts +17 -0
  174. package/types/export/index.d.ts +243 -0
  175. package/types/geometry/index.d.ts +164 -0
  176. package/types/math/index.d.ts +214 -0
  177. package/types/render/LayerPresetManager.d.ts +78 -0
  178. package/types/render/LayerReactivityBridge.d.ts +85 -0
  179. package/types/render/LayerRelationshipGraph.d.ts +174 -0
  180. package/types/render/index.d.ts +3 -0
  181. package/types/scene/index.d.ts +204 -0
  182. package/types/systems/index.d.ts +244 -0
  183. package/types/variations/index.d.ts +62 -0
  184. package/types/viewer/index.d.ts +225 -0
  185. package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +0 -34
  186. package/DOCS/DEV_TRACK_ANALYSIS.md +0 -77
  187. package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +0 -42
  188. package/DOCS/SESSION_014_PLAN.md +0 -195
  189. package/DOCS/SESSION_LOG_2026-01-07.md +0 -56
  190. package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +0 -72
  191. package/DOCS/SYSTEM_AUDIT_2026-01-30.md +0 -738
  192. /package/src/viewer/{ReactivityManager.js → ViewerInputHandler.js} +0 -0
@@ -0,0 +1,641 @@
1
+ /**
2
+ * GlyphWarVisualizer.js - VIB3+ Visual Integration for GLYPH_WAR
3
+ *
4
+ * Maps game state (idle, dueling, sudden death, victory) to VIB3+ holographic
5
+ * layer parameters, transitions, post-processing, and a 10-second sudden-death
6
+ * timeline. Chromatic aberration is the primary tension signal.
7
+ *
8
+ * Designed via /vib3-design skill — Artifact Mode.
9
+ *
10
+ * @module games/glyph-war/GlyphWarVisualizer
11
+ * @version 1.0.0
12
+ */
13
+
14
+ import { TransitionAnimator } from '../../creative/TransitionAnimator.js';
15
+ import { ParameterTimeline } from '../../creative/ParameterTimeline.js';
16
+ import { PostProcessingPipeline } from '../../creative/PostProcessingPipeline.js';
17
+ import { ColorPresetsSystem } from '../../creative/ColorPresetsSystem.js';
18
+ import { ChoreographyPlayer } from '../../creative/ChoreographyPlayer.js';
19
+
20
+ // ─────────────────────────────────────────────────────────────────────────────
21
+ // Visual State Presets (designed via /vib3-design Workflow 2)
22
+ // ─────────────────────────────────────────────────────────────────────────────
23
+
24
+ /**
25
+ * 4 game states mapped to VIB3+ parameter snapshots.
26
+ *
27
+ * Each state targets the holographic system with a specific geometry,
28
+ * color preset, post-FX chain, and tuned parameters. Geometry choices:
29
+ * - Idle: 3 (torus) — smooth, waiting
30
+ * - Dueling: 11 (hypersphere+torus) — flowing, organic tension
31
+ * - SuddenDeath: 17 (hypertetra+hypercube) — aggressive, angular
32
+ * - Victory: 8 (hypersphere+tetra) — expansive, resolved
33
+ */
34
+ export const GAME_STATES = {
35
+ idle: {
36
+ system: 'holographic',
37
+ geometry: 3,
38
+ colorPreset: 'Monochrome',
39
+ postFxChain: 'Clean',
40
+ params: {
41
+ hue: 0,
42
+ saturation: 0.0,
43
+ intensity: 0.3,
44
+ speed: 0.3,
45
+ chaos: 0.0,
46
+ morphFactor: 0.0,
47
+ gridDensity: 12,
48
+ dimension: 4.2,
49
+ rot4dXY: 0,
50
+ rot4dXZ: 0,
51
+ rot4dYZ: 0,
52
+ rot4dXW: 0,
53
+ rot4dYW: 0,
54
+ rot4dZW: 0
55
+ }
56
+ },
57
+
58
+ dueling: {
59
+ system: 'holographic',
60
+ geometry: 11,
61
+ colorPreset: 'Cyberpunk',
62
+ postFxChain: 'Holographic',
63
+ params: {
64
+ hue: 280,
65
+ saturation: 0.9,
66
+ intensity: 0.6,
67
+ speed: 1.0,
68
+ chaos: 0.15,
69
+ morphFactor: 0.3,
70
+ gridDensity: 24,
71
+ dimension: 3.8,
72
+ rot4dXY: 0,
73
+ rot4dXZ: 0.3,
74
+ rot4dYZ: 0,
75
+ rot4dXW: 0.8,
76
+ rot4dYW: 0.5,
77
+ rot4dZW: 1.2
78
+ }
79
+ },
80
+
81
+ suddenDeath: {
82
+ system: 'holographic',
83
+ geometry: 17,
84
+ colorPreset: 'Neon',
85
+ postFxChain: 'Glitch Art',
86
+ params: {
87
+ hue: 300,
88
+ saturation: 1.0,
89
+ intensity: 0.9,
90
+ speed: 2.5,
91
+ chaos: 0.7,
92
+ morphFactor: 1.4,
93
+ gridDensity: 60,
94
+ dimension: 3.2,
95
+ rot4dXY: 0,
96
+ rot4dXZ: 0.5,
97
+ rot4dYZ: 0.3,
98
+ rot4dXW: 2.0,
99
+ rot4dYW: 1.5,
100
+ rot4dZW: 2.8
101
+ }
102
+ },
103
+
104
+ victory: {
105
+ system: 'holographic',
106
+ geometry: 8,
107
+ colorPreset: 'Aurora',
108
+ postFxChain: 'Cinematic',
109
+ params: {
110
+ hue: 140,
111
+ saturation: 0.7,
112
+ intensity: 0.8,
113
+ speed: 0.6,
114
+ chaos: 0.0,
115
+ morphFactor: 0.1,
116
+ gridDensity: 8,
117
+ dimension: 4.0,
118
+ rot4dXY: 0,
119
+ rot4dXZ: 0,
120
+ rot4dYZ: 0,
121
+ rot4dXW: 0.3,
122
+ rot4dYW: 0.2,
123
+ rot4dZW: 0.4
124
+ }
125
+ }
126
+ };
127
+
128
+ // ─────────────────────────────────────────────────────────────────────────────
129
+ // Transition Definitions (designed via /vib3-design Workflow 4)
130
+ // ─────────────────────────────────────────────────────────────────────────────
131
+
132
+ /**
133
+ * Transitions between game states.
134
+ * Key: `${fromState}:${toState}`
135
+ */
136
+ export const TRANSITIONS = {
137
+ 'idle:dueling': { duration: 800, easing: 'easeOut' },
138
+ 'dueling:suddenDeath': { duration: 300, easing: 'elastic' },
139
+ 'suddenDeath:victory': { duration: 1200, easing: 'backOut' },
140
+ 'dueling:victory': { duration: 1200, easing: 'backOut' },
141
+ 'victory:idle': { duration: 1000, easing: 'easeInOut' },
142
+ 'idle:idle': { duration: 500, easing: 'easeInOut' }
143
+ };
144
+
145
+ // ─────────────────────────────────────────────────────────────────────────────
146
+ // Sudden Death Timeline (designed via /vib3-design Workflow 3)
147
+ // 10-second escalation from tense → screen-tearing
148
+ // ─────────────────────────────────────────────────────────────────────────────
149
+
150
+ /**
151
+ * ParameterTimeline spec for the 10-second sudden death countdown.
152
+ * Chromatic aberration is driven externally (see TensionMapper).
153
+ */
154
+ export const SUDDEN_DEATH_TIMELINE = {
155
+ duration: 10000,
156
+ loopMode: 'once',
157
+ tracks: {
158
+ hue: {
159
+ keyframes: [
160
+ { time: 0, value: 200, easing: 'linear' },
161
+ { time: 3000, value: 320, easing: 'easeIn' },
162
+ { time: 7000, value: 0, easing: 'exponential' },
163
+ { time: 9000, value: 0, easing: 'elastic' },
164
+ { time: 10000, value: 0, easing: 'linear' }
165
+ ]
166
+ },
167
+ chaos: {
168
+ keyframes: [
169
+ { time: 0, value: 0.3, easing: 'linear' },
170
+ { time: 3000, value: 0.5, easing: 'easeIn' },
171
+ { time: 7000, value: 0.8, easing: 'expoOut' },
172
+ { time: 9000, value: 1.0, easing: 'elastic' },
173
+ { time: 10000, value: 1.0, easing: 'linear' }
174
+ ]
175
+ },
176
+ speed: {
177
+ keyframes: [
178
+ { time: 0, value: 1.5, easing: 'linear' },
179
+ { time: 3000, value: 2.0, easing: 'easeIn' },
180
+ { time: 7000, value: 2.8, easing: 'expoOut' },
181
+ { time: 9000, value: 3.0, easing: 'elastic' },
182
+ { time: 10000, value: 3.0, easing: 'linear' }
183
+ ]
184
+ },
185
+ gridDensity: {
186
+ keyframes: [
187
+ { time: 0, value: 30, easing: 'linear' },
188
+ { time: 3000, value: 45, easing: 'easeIn' },
189
+ { time: 7000, value: 70, easing: 'expoOut' },
190
+ { time: 9000, value: 100, easing: 'elastic' },
191
+ { time: 10000, value: 100, easing: 'linear' }
192
+ ]
193
+ },
194
+ rot4dXW: {
195
+ keyframes: [
196
+ { time: 0, value: 2.0, easing: 'linear' },
197
+ { time: 10000, value: 6.28, easing: 'linear' }
198
+ ]
199
+ },
200
+ intensity: {
201
+ keyframes: [
202
+ { time: 0, value: 0.7, easing: 'linear' },
203
+ { time: 7000, value: 0.9, easing: 'easeIn' },
204
+ { time: 9500, value: 1.0, easing: 'elastic' },
205
+ { time: 10000, value: 1.0, easing: 'linear' }
206
+ ]
207
+ }
208
+ }
209
+ };
210
+
211
+ // ─────────────────────────────────────────────────────────────────────────────
212
+ // Parallax Layer Config (holographic 5-layer stack)
213
+ // ─────────────────────────────────────────────────────────────────────────────
214
+
215
+ /**
216
+ * Parallax multipliers per holographic layer.
217
+ * Applied to spatial input (tilt/mouse) and 4D rotation deltas.
218
+ * Factor 0.0 = screen-fixed, 1.0 = direct tracking, >1.0 = exaggerated.
219
+ */
220
+ export const LAYER_PARALLAX = {
221
+ 'holo-background-canvas': {
222
+ role: 'Deep void',
223
+ parallax: 0.1,
224
+ baseOpacity: 0.4,
225
+ rotationCounterFactor: -0.3 // slow counter-rotation
226
+ },
227
+ 'holo-shadow-canvas': {
228
+ role: 'Interference mesh',
229
+ parallax: 0.5,
230
+ baseOpacity: 0.6,
231
+ rotationCounterFactor: -0.15
232
+ },
233
+ 'holo-content-canvas': {
234
+ role: 'Letter refraction plane',
235
+ parallax: 1.0,
236
+ baseOpacity: 1.0,
237
+ rotationCounterFactor: 0
238
+ },
239
+ 'holo-highlight-canvas': {
240
+ role: 'Contested letter glow',
241
+ parallax: 1.5,
242
+ baseOpacity: 0.0, // only visible during conflicts
243
+ rotationCounterFactor: 0
244
+ },
245
+ 'holo-accent-canvas': {
246
+ role: 'HUD bezel + CA',
247
+ parallax: 0.0, // screen-fixed
248
+ baseOpacity: 0.8,
249
+ rotationCounterFactor: 0
250
+ }
251
+ };
252
+
253
+ // ─────────────────────────────────────────────────────────────────────────────
254
+ // Tension → Chromatic Aberration Mapper
255
+ // ─────────────────────────────────────────────────────────────────────────────
256
+
257
+ /**
258
+ * Compute chromatic aberration intensity from game tension signals.
259
+ *
260
+ * CA is the primary visual metaphor for "system stress":
261
+ * - Base: 0.02 (subtle glass refraction)
262
+ * - +0.15 per contested letter (both players want it)
263
+ * - During sudden death: inversely maps timer to CA (1s left = 2.0)
264
+ *
265
+ * @param {Object} tension - Tension state
266
+ * @param {number} tension.contestedLetters - Count of letters both players want
267
+ * @param {boolean} tension.suddenDeath - Whether sudden death is active
268
+ * @param {number} tension.secondsLeft - Seconds remaining in sudden death (0-10)
269
+ * @returns {number} Chromatic aberration strength (0.02 - ~2.5)
270
+ */
271
+ export function computeChromaticAberration(tension) {
272
+ const BASE_CA = 0.02;
273
+ const PER_CONFLICT = 0.15;
274
+ const MAX_CONFLICT_CA = 0.6;
275
+
276
+ let ca = BASE_CA;
277
+
278
+ // Contested letter tension
279
+ const conflictCA = Math.min(
280
+ (tension.contestedLetters || 0) * PER_CONFLICT,
281
+ MAX_CONFLICT_CA
282
+ );
283
+ ca += conflictCA;
284
+
285
+ // Sudden death timer mapping
286
+ if (tension.suddenDeath && typeof tension.secondsLeft === 'number') {
287
+ const timerPercent = Math.max(0, Math.min(1, tension.secondsLeft / 10));
288
+ const timerCA = (1 - timerPercent) * 2.0;
289
+ ca += timerCA;
290
+ }
291
+
292
+ return ca;
293
+ }
294
+
295
+ // ─────────────────────────────────────────────────────────────────────────────
296
+ // Game Event → VIB3 Parameter Reactive Bindings
297
+ // ─────────────────────────────────────────────────────────────────────────────
298
+
299
+ /**
300
+ * Maps discrete game events to VIB3+ parameter impulses.
301
+ * Each binding returns a partial param object for TransitionAnimator.
302
+ */
303
+ export const EVENT_BINDINGS = {
304
+ /**
305
+ * Player grabs a letter from the pile.
306
+ * Each held letter shifts deeper into 4D hyperspace.
307
+ * @param {number} totalHeld - Total letters held by this player
308
+ */
309
+ letterGrabbed(totalHeld) {
310
+ return {
311
+ params: { rot4dXW: 0.8 + totalHeld * 0.1 },
312
+ duration: 200,
313
+ easing: 'easeOut'
314
+ };
315
+ },
316
+
317
+ /**
318
+ * Both players want the same letter (tether/conflict).
319
+ * Highlight layer pulses, CA spikes.
320
+ * @param {number} contestCount - Number of contested letters
321
+ */
322
+ letterConflict(contestCount) {
323
+ return {
324
+ params: {
325
+ intensity: 0.6 + contestCount * 0.05
326
+ },
327
+ duration: 150,
328
+ easing: 'elastic'
329
+ };
330
+ },
331
+
332
+ /**
333
+ * Player is rapidly placing letters (flow state).
334
+ * Speed increases, shadow layer thickens.
335
+ * @param {number} wordLength - Current word length
336
+ */
337
+ wordGrowing(wordLength) {
338
+ const speedBoost = Math.min(wordLength * 0.15, 1.0);
339
+ return {
340
+ params: {
341
+ speed: 1.0 + speedBoost
342
+ },
343
+ duration: 300,
344
+ easing: 'easeOut'
345
+ };
346
+ },
347
+
348
+ /**
349
+ * Player dissolves their word — letters scatter back to pool.
350
+ * VHS glitch: geometry snaps to points, scanline tear.
351
+ */
352
+ dissolve() {
353
+ return {
354
+ params: {
355
+ morphFactor: 2.0,
356
+ chaos: 0.9,
357
+ speed: 3.0
358
+ },
359
+ duration: 200,
360
+ easing: 'linear',
361
+ // Caller should schedule a snapback after 200ms
362
+ snapback: {
363
+ params: { morphFactor: 0.3, chaos: 0.15, speed: 1.0 },
364
+ duration: 400,
365
+ easing: 'easeOut'
366
+ }
367
+ };
368
+ },
369
+
370
+ /**
371
+ * ATTACK pressed — transition to sudden death.
372
+ */
373
+ attack() {
374
+ return {
375
+ params: GAME_STATES.suddenDeath.params,
376
+ duration: 300,
377
+ easing: 'elastic'
378
+ };
379
+ },
380
+
381
+ /**
382
+ * Round won — transition to victory.
383
+ * @param {string} _winner - 'p1' or 'p2' (for future per-player effects)
384
+ */
385
+ victory(_winner) {
386
+ return {
387
+ params: {
388
+ ...GAME_STATES.victory.params,
389
+ intensity: 1.0 // bloom swell
390
+ },
391
+ duration: 1200,
392
+ easing: 'backOut'
393
+ };
394
+ }
395
+ };
396
+
397
+ // ─────────────────────────────────────────────────────────────────────────────
398
+ // GlyphWarVisualizer Class
399
+ // ─────────────────────────────────────────────────────────────────────────────
400
+
401
+ /**
402
+ * Orchestrates all VIB3+ visual behavior for GLYPH_WAR.
403
+ *
404
+ * Lifecycle:
405
+ * 1. Construct with a VIB3Engine instance
406
+ * 2. Call init() to set up holographic system + post-processing
407
+ * 3. Call setState() on game state transitions
408
+ * 4. Call onGameEvent() for reactive per-frame bindings
409
+ * 5. Call updateTension() each frame with current conflict/timer data
410
+ * 6. Call destroy() on teardown
411
+ *
412
+ * @example
413
+ * const viz = new GlyphWarVisualizer(engine, containerEl);
414
+ * await viz.init();
415
+ * viz.setState('idle');
416
+ * // ... game starts ...
417
+ * viz.setState('dueling');
418
+ * viz.onGameEvent('letterGrabbed', 3);
419
+ * viz.updateTension({ contestedLetters: 2, suddenDeath: false, secondsLeft: 10 });
420
+ */
421
+ export class GlyphWarVisualizer {
422
+ /**
423
+ * @param {Object} engine - VIB3Engine instance
424
+ * @param {HTMLElement} container - DOM container for post-processing target
425
+ */
426
+ constructor(engine, container) {
427
+ if (!engine) throw new Error('GlyphWarVisualizer requires a VIB3Engine');
428
+
429
+ /** @type {Object} */
430
+ this.engine = engine;
431
+
432
+ /** @type {HTMLElement} */
433
+ this.container = container;
434
+
435
+ /** @type {string} Current game state name */
436
+ this.currentState = 'idle';
437
+
438
+ /** @type {TransitionAnimator} */
439
+ this.animator = new TransitionAnimator(
440
+ (name, value) => this.engine.setParameter(name, value),
441
+ (name) => this.engine.getParameter?.(name) ?? 0
442
+ );
443
+
444
+ /** @type {ParameterTimeline|null} Sudden death timeline */
445
+ this.deathTimeline = null;
446
+
447
+ /** @type {PostProcessingPipeline|null} */
448
+ this.postFx = null;
449
+
450
+ /** @type {ColorPresetsSystem|null} */
451
+ this.colors = null;
452
+
453
+ /** @type {number} Current chromatic aberration value */
454
+ this._currentCA = 0.02;
455
+
456
+ /** @type {number|null} rAF ID for tension updates */
457
+ this._tensionFrameId = null;
458
+ }
459
+
460
+ /**
461
+ * Initialize: switch to holographic system, set up creative tooling.
462
+ */
463
+ async init() {
464
+ // Switch to holographic system
465
+ if (this.engine.switchSystem) {
466
+ await this.engine.switchSystem('holographic');
467
+ }
468
+
469
+ // Set up color presets
470
+ this.colors = new ColorPresetsSystem(
471
+ (name, value) => this.engine.setParameter(name, value)
472
+ );
473
+
474
+ // Set up post-processing pipeline
475
+ if (this.container) {
476
+ this.postFx = new PostProcessingPipeline(this.container);
477
+ }
478
+
479
+ // Apply idle state
480
+ this.setState('idle');
481
+ }
482
+
483
+ /**
484
+ * Transition to a new game state.
485
+ *
486
+ * @param {'idle'|'dueling'|'suddenDeath'|'victory'} stateName
487
+ */
488
+ setState(stateName) {
489
+ const state = GAME_STATES[stateName];
490
+ if (!state) {
491
+ console.warn(`GlyphWarVisualizer: Unknown state "${stateName}"`);
492
+ return;
493
+ }
494
+
495
+ const transitionKey = `${this.currentState}:${stateName}`;
496
+ const transition = TRANSITIONS[transitionKey] || { duration: 500, easing: 'easeInOut' };
497
+
498
+ // Stop any running sudden death timeline
499
+ if (stateName !== 'suddenDeath' && this.deathTimeline) {
500
+ this.deathTimeline.stop();
501
+ this.deathTimeline = null;
502
+ }
503
+
504
+ // Set geometry immediately (not interpolatable)
505
+ this.engine.setParameter('geometry', state.geometry);
506
+
507
+ // Apply color preset
508
+ if (this.colors && state.colorPreset) {
509
+ this.colors.applyPreset(state.colorPreset);
510
+ }
511
+
512
+ // Apply post-processing chain
513
+ if (this.postFx && state.postFxChain) {
514
+ this.postFx.loadPresetChain(state.postFxChain);
515
+ this.postFx.apply();
516
+ }
517
+
518
+ // Smooth transition of continuous parameters
519
+ this.animator.cancelAll();
520
+ this.animator.transition(
521
+ state.params,
522
+ transition.duration,
523
+ transition.easing
524
+ );
525
+
526
+ // Start sudden death timeline if entering that state
527
+ if (stateName === 'suddenDeath') {
528
+ this._startSuddenDeathTimeline();
529
+ }
530
+
531
+ this.currentState = stateName;
532
+ }
533
+
534
+ /**
535
+ * Handle a discrete game event with a reactive visual impulse.
536
+ *
537
+ * @param {string} eventName - Key from EVENT_BINDINGS
538
+ * @param {...*} args - Arguments forwarded to the binding function
539
+ */
540
+ onGameEvent(eventName, ...args) {
541
+ const binding = EVENT_BINDINGS[eventName];
542
+ if (!binding) return;
543
+
544
+ const impulse = binding(...args);
545
+ if (!impulse) return;
546
+
547
+ this.animator.transition(
548
+ impulse.params,
549
+ impulse.duration,
550
+ impulse.easing
551
+ );
552
+
553
+ // Handle snapback (e.g., dissolve glitch then recover)
554
+ if (impulse.snapback) {
555
+ setTimeout(() => {
556
+ this.animator.transition(
557
+ impulse.snapback.params,
558
+ impulse.snapback.duration,
559
+ impulse.snapback.easing
560
+ );
561
+ }, impulse.duration);
562
+ }
563
+ }
564
+
565
+ /**
566
+ * Update tension-reactive visuals (call each frame or on state change).
567
+ *
568
+ * @param {Object} tension
569
+ * @param {number} tension.contestedLetters
570
+ * @param {boolean} tension.suddenDeath
571
+ * @param {number} tension.secondsLeft
572
+ */
573
+ updateTension(tension) {
574
+ this._currentCA = computeChromaticAberration(tension);
575
+
576
+ // Apply CA to post-processing pipeline
577
+ if (this.postFx) {
578
+ this.postFx.addEffect('chromaticAberration', {
579
+ strength: this._currentCA
580
+ });
581
+ this.postFx.apply();
582
+ }
583
+
584
+ // Highlight layer opacity tracks conflict count
585
+ // (In a full impl this would target the specific holo-highlight canvas)
586
+ const highlightOpacity = Math.min(0.3 + (tension.contestedLetters || 0) * 0.15, 1.0);
587
+ this.engine.setParameter('intensity',
588
+ GAME_STATES[this.currentState]?.params?.intensity ?? 0.5 +
589
+ highlightOpacity * 0.2
590
+ );
591
+ }
592
+
593
+ /**
594
+ * Get current chromatic aberration value (for UI sync).
595
+ * @returns {number}
596
+ */
597
+ getChromaticAberration() {
598
+ return this._currentCA;
599
+ }
600
+
601
+ /**
602
+ * Clean up all resources.
603
+ */
604
+ destroy() {
605
+ this.animator.cancelAll();
606
+ if (this.deathTimeline) {
607
+ this.deathTimeline.stop();
608
+ this.deathTimeline = null;
609
+ }
610
+ if (this.postFx) {
611
+ this.postFx.clearAll?.();
612
+ }
613
+ if (this._tensionFrameId) {
614
+ cancelAnimationFrame(this._tensionFrameId);
615
+ }
616
+ }
617
+
618
+ // ─── Internal ────────────────────────────────────────────────────────────
619
+
620
+ /**
621
+ * Build and start the 10-second sudden death ParameterTimeline.
622
+ * @private
623
+ */
624
+ _startSuddenDeathTimeline() {
625
+ this.deathTimeline = new ParameterTimeline(
626
+ (name, value) => this.engine.setParameter(name, value)
627
+ );
628
+
629
+ this.deathTimeline.setDuration(SUDDEN_DEATH_TIMELINE.duration);
630
+ this.deathTimeline.setLoopMode(SUDDEN_DEATH_TIMELINE.loopMode);
631
+
632
+ for (const [param, track] of Object.entries(SUDDEN_DEATH_TIMELINE.tracks)) {
633
+ this.deathTimeline.addTrack(param);
634
+ for (const kf of track.keyframes) {
635
+ this.deathTimeline.addKeyframe(param, kf.time, kf.value, kf.easing);
636
+ }
637
+ }
638
+
639
+ this.deathTimeline.play();
640
+ }
641
+ }
@@ -61,8 +61,8 @@ export function generate24CellVertices(size = 1) {
61
61
  ];
62
62
  for (const [s1, s2] of signs) {
63
63
  const v = new Vec4(0, 0, 0, 0);
64
- v.data[i] = s1 * s;
65
- v.data[j] = s2 * s;
64
+ v.setComponent(i, s1 * s);
65
+ v.setComponent(j, s2 * s);
66
66
  vertices.push(v);
67
67
  }
68
68
  }