@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.
- package/CHANGELOG.md +36 -0
- package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +245 -0
- package/DOCS/ANDROID_DEPLOYMENT.md +59 -0
- package/DOCS/ARCHITECTURE.md +1 -0
- package/DOCS/CI_TESTING.md +2 -0
- package/DOCS/CLI_ONBOARDING.md +3 -1
- package/DOCS/CONTROL_REFERENCE.md +2 -0
- package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +119 -0
- package/DOCS/ENV_SETUP.md +2 -0
- package/DOCS/EPIC_SCROLL_EVENTS.md +775 -0
- package/DOCS/EXPANSION_DESIGN.md +979 -0
- package/DOCS/EXPANSION_DESIGN_ULTRA.md +389 -0
- package/DOCS/EXPORT_FORMATS.md +2 -0
- package/DOCS/GPU_DISPOSAL_GUIDE.md +2 -0
- package/DOCS/HANDOFF_LANDING_PAGE.md +156 -0
- package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +495 -0
- package/DOCS/LICENSING_TIERS.md +2 -0
- package/DOCS/MASTER_PLAN_2026-01-31.md +4 -2
- package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +939 -0
- package/DOCS/OBS_SETUP_GUIDE.md +2 -0
- package/DOCS/OPTIMIZATION_PLAN_MATH.md +119 -0
- package/DOCS/PRODUCT_STRATEGY.md +65 -0
- package/DOCS/PROJECT_SETUP.md +2 -0
- package/DOCS/README.md +105 -0
- package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +99 -0
- package/DOCS/RENDERER_LIFECYCLE.md +2 -0
- package/DOCS/REPO_MANIFEST.md +2 -0
- package/DOCS/ROADMAP.md +113 -0
- package/DOCS/SCROLL_TIMELINE_v3.md +271 -0
- package/DOCS/SITE_REFACTOR_PLAN.md +102 -0
- package/DOCS/STATUS.md +26 -0
- package/DOCS/SYSTEM_INVENTORY.md +37 -32
- package/DOCS/TELEMETRY_EXPORTS.md +2 -0
- package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +87 -0
- package/DOCS/VISUAL_ANALYSIS_FACETAD.md +135 -0
- package/DOCS/VISUAL_ANALYSIS_SIMONE.md +97 -0
- package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +88 -0
- package/DOCS/WEBGPU_STATUS.md +121 -38
- package/DOCS/XR_BENCHMARKS.md +2 -0
- package/DOCS/archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +1 -0
- package/DOCS/archive/DEV_TRACK_ANALYSIS.md +1 -0
- package/DOCS/archive/DEV_TRACK_PLAN_2026-01-07.md +1 -0
- package/DOCS/archive/SESSION_014_PLAN.md +1 -0
- package/DOCS/archive/SESSION_LOG_2026-01-07.md +1 -0
- package/DOCS/archive/STRATEGIC_BLUEPRINT_2026-01-07.md +1 -0
- package/DOCS/archive/SYSTEM_AUDIT_2026-01-30.md +1 -0
- package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +1 -0
- package/DOCS/{DEV_TRACK_SESSION_2026-01-31.md → dev-tracks/DEV_TRACK_SESSION_2026-01-31.md} +3 -1
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +233 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +129 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +144 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +110 -0
- package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +310 -0
- package/DOCS/dev-tracks/README.md +12 -0
- package/README.md +26 -13
- package/cpp/CMakeLists.txt +236 -0
- package/cpp/bindings/embind.cpp +269 -0
- package/cpp/build.sh +129 -0
- package/cpp/geometry/Crystal.cpp +103 -0
- package/cpp/geometry/Fractal.cpp +136 -0
- package/cpp/geometry/GeometryGenerator.cpp +262 -0
- package/cpp/geometry/KleinBottle.cpp +71 -0
- package/cpp/geometry/Sphere.cpp +134 -0
- package/cpp/geometry/Tesseract.cpp +94 -0
- package/cpp/geometry/Tetrahedron.cpp +83 -0
- package/cpp/geometry/Torus.cpp +65 -0
- package/cpp/geometry/WarpFunctions.cpp +238 -0
- package/cpp/geometry/Wave.cpp +85 -0
- package/cpp/include/vib3_ffi.h +238 -0
- package/cpp/math/Mat4x4.cpp +409 -0
- package/cpp/math/Mat4x4.hpp +209 -0
- package/cpp/math/Projection.cpp +142 -0
- package/cpp/math/Projection.hpp +148 -0
- package/cpp/math/Rotor4D.cpp +322 -0
- package/cpp/math/Rotor4D.hpp +204 -0
- package/cpp/math/Vec4.cpp +303 -0
- package/cpp/math/Vec4.hpp +225 -0
- package/cpp/src/vib3_ffi.cpp +607 -0
- package/cpp/tests/Geometry_test.cpp +213 -0
- package/cpp/tests/Mat4x4_test.cpp +494 -0
- package/cpp/tests/Projection_test.cpp +298 -0
- package/cpp/tests/Rotor4D_test.cpp +423 -0
- package/cpp/tests/Vec4_test.cpp +489 -0
- package/docs/webgpu-live.html +1 -1
- package/package.json +41 -30
- package/src/agent/index.js +1 -3
- package/src/agent/mcp/MCPServer.js +1220 -144
- package/src/agent/mcp/index.js +1 -1
- package/src/agent/mcp/stdio-server.js +264 -0
- package/src/agent/mcp/tools.js +498 -31
- package/src/cli/index.js +431 -47
- package/src/core/CanvasManager.js +97 -204
- package/src/core/ErrorReporter.js +1 -1
- package/src/core/Parameters.js +1 -1
- package/src/core/VIB3Engine.js +93 -4
- package/src/core/VitalitySystem.js +53 -0
- package/src/core/index.js +18 -0
- package/src/core/renderers/FacetedRendererAdapter.js +10 -9
- package/src/core/renderers/HolographicRendererAdapter.js +13 -9
- package/src/core/renderers/QuantumRendererAdapter.js +11 -7
- package/src/creative/AestheticMapper.js +628 -0
- package/src/creative/ChoreographyPlayer.js +481 -0
- package/src/creative/index.js +11 -0
- package/src/experimental/GameLoop.js +72 -0
- package/src/experimental/LatticePhysics.js +100 -0
- package/src/experimental/LiveDirector.js +143 -0
- package/src/experimental/PlayerController4D.js +154 -0
- package/src/experimental/VIB3Actor.js +138 -0
- package/src/experimental/VIB3Compositor.js +117 -0
- package/src/experimental/VIB3Link.js +122 -0
- package/src/experimental/VIB3Orchestrator.js +146 -0
- package/src/experimental/VIB3Universe.js +109 -0
- package/src/experimental/demos/CrystalLabyrinth.js +202 -0
- package/src/export/TradingCardManager.js +3 -4
- package/src/export/index.js +11 -1
- package/src/faceted/FacetedSystem.js +260 -394
- package/src/games/glyph-war/GlyphWarVisualizer.js +641 -0
- package/src/geometry/generators/Crystal.js +2 -2
- package/src/geometry/warp/HypersphereCore.js +53 -24
- package/src/holograms/HolographicVisualizer.js +84 -98
- package/src/holograms/RealHolographicSystem.js +194 -43
- package/src/math/Mat4x4.js +308 -105
- package/src/math/Rotor4D.js +124 -40
- package/src/math/Vec4.js +200 -103
- package/src/math/index.js +7 -7
- package/src/polychora/PolychoraSystem.js +77 -0
- package/src/quantum/QuantumEngine.js +103 -66
- package/src/quantum/QuantumVisualizer.js +31 -22
- package/src/reactivity/index.js +3 -5
- package/src/render/LayerPresetManager.js +372 -0
- package/src/render/LayerReactivityBridge.js +344 -0
- package/src/render/LayerRelationshipGraph.js +610 -0
- package/src/render/MultiCanvasBridge.js +148 -25
- package/src/render/ShaderLoader.js +38 -0
- package/src/render/ShaderProgram.js +4 -4
- package/src/render/UnifiedRenderBridge.js +4 -1
- package/src/render/backends/WebGPUBackend.js +8 -4
- package/src/render/index.js +27 -2
- package/src/scene/Node4D.js +74 -24
- package/src/scene/index.js +4 -4
- package/src/shaders/common/geometry24.glsl +65 -0
- package/src/shaders/common/geometry24.wgsl +54 -0
- package/src/shaders/common/rotation4d.glsl +4 -4
- package/src/shaders/common/rotation4d.wgsl +2 -2
- package/src/shaders/common/uniforms.wgsl +15 -8
- package/src/shaders/faceted/faceted.frag.glsl +220 -80
- package/src/shaders/faceted/faceted.frag.wgsl +144 -90
- package/src/shaders/holographic/holographic.frag.glsl +28 -9
- package/src/shaders/holographic/holographic.frag.wgsl +112 -41
- package/src/shaders/quantum/quantum.frag.glsl +1 -0
- package/src/shaders/quantum/quantum.frag.wgsl +6 -4
- package/src/testing/ParallelTestFramework.js +2 -2
- package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +2 -2
- package/src/viewer/GalleryUI.js +17 -0
- package/src/viewer/ViewerPortal.js +2 -2
- package/src/viewer/index.js +1 -1
- package/tools/headless-renderer.js +258 -0
- package/tools/shader-sync-verify.js +14 -8
- package/tools/site-analysis/all-reports.json +32 -0
- package/tools/site-analysis/combined-analysis.md +50 -0
- package/tools/site-analyzer.mjs +779 -0
- package/tools/visual-catalog/capture.js +276 -0
- package/tools/visual-catalog/composite.js +138 -0
- package/types/adaptive-sdk.d.ts +204 -5
- package/types/agent/cli.d.ts +78 -0
- package/types/agent/index.d.ts +18 -0
- package/types/agent/mcp.d.ts +87 -0
- package/types/agent/telemetry.d.ts +190 -0
- package/types/core/VIB3Engine.d.ts +26 -0
- package/types/core/index.d.ts +261 -0
- package/types/creative/AestheticMapper.d.ts +72 -0
- package/types/creative/ChoreographyPlayer.d.ts +96 -0
- package/types/creative/index.d.ts +17 -0
- package/types/export/index.d.ts +243 -0
- package/types/geometry/index.d.ts +164 -0
- package/types/math/index.d.ts +214 -0
- package/types/render/LayerPresetManager.d.ts +78 -0
- package/types/render/LayerReactivityBridge.d.ts +85 -0
- package/types/render/LayerRelationshipGraph.d.ts +174 -0
- package/types/render/index.d.ts +3 -0
- package/types/scene/index.d.ts +204 -0
- package/types/systems/index.d.ts +244 -0
- package/types/variations/index.d.ts +62 -0
- package/types/viewer/index.d.ts +225 -0
- package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +0 -34
- package/DOCS/DEV_TRACK_ANALYSIS.md +0 -77
- package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +0 -42
- package/DOCS/SESSION_014_PLAN.md +0 -195
- package/DOCS/SESSION_LOG_2026-01-07.md +0 -56
- package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +0 -72
- package/DOCS/SYSTEM_AUDIT_2026-01-30.md +0 -738
- /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.
|
|
65
|
-
v.
|
|
64
|
+
v.setComponent(i, s1 * s);
|
|
65
|
+
v.setComponent(j, s2 * s);
|
|
66
66
|
vertices.push(v);
|
|
67
67
|
}
|
|
68
68
|
}
|