@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,979 @@
|
|
|
1
|
+
Last reviewed: 2026-02-17
|
|
2
|
+
|
|
3
|
+
# VIB3+ Premium Tier — Expansion Design Document
|
|
4
|
+
|
|
5
|
+
**Purpose**: Technical specification for `@vib3code/premium`, a separate npm package that extends the free `@vib3code/sdk` with fine-grained shader control, axis locking, per-layer geometry, event-triggered state changes, and live CSS/framework integration.
|
|
6
|
+
|
|
7
|
+
**Status**: Design document. No code implemented yet.
|
|
8
|
+
**Date**: Feb 16, 2026
|
|
9
|
+
**Based on**: Deep analysis of all shader GLSL, layer system, event architecture, and licensing model in the free SDK.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Architecture Overview
|
|
14
|
+
|
|
15
|
+
### Package Relationship
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
@vib3code/sdk (free, MIT) @vib3code/premium (paid)
|
|
19
|
+
┌──────────────────────────┐ ┌──────────────────────────┐
|
|
20
|
+
│ VIB3Engine │◄──────│ enablePremium(engine) │
|
|
21
|
+
│ 3 visualization systems │ │ │
|
|
22
|
+
│ 24 geometries │ │ ShaderParameterSurface │
|
|
23
|
+
│ LayerRelationshipGraph │ │ RotationLockSystem │
|
|
24
|
+
│ ChoreographyPlayer │ │ LayerGeometryMixer │
|
|
25
|
+
│ TransitionAnimator │ │ VisualEventSystem │
|
|
26
|
+
│ ColorPresetsSystem │ │ CSSBridge │
|
|
27
|
+
│ AestheticMapper │ │ ChoreographyExtensions │
|
|
28
|
+
│ 14 core MCP tools │ │ FrameworkSync │
|
|
29
|
+
│ ReactivityManager │ │ 8+ premium MCP tools │
|
|
30
|
+
│ SpatialInputSystem │ │ │
|
|
31
|
+
│ onParameterChange() │ │ PremiumMCPServer │
|
|
32
|
+
└──────────────────────────┘ └──────────────────────────┘
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Premium imports from free SDK as a **peer dependency**. Free SDK never imports from premium. One-directional dependency.
|
|
36
|
+
|
|
37
|
+
### How Premium Wraps the Engine
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
import { VIB3Engine } from '@vib3code/sdk';
|
|
41
|
+
import { enablePremium } from '@vib3code/premium';
|
|
42
|
+
|
|
43
|
+
const engine = new VIB3Engine({ system: 'holographic' });
|
|
44
|
+
await engine.initialize(container);
|
|
45
|
+
|
|
46
|
+
const premium = enablePremium(engine, {
|
|
47
|
+
licenseKey: 'VIB3-PRO-xxxx-xxxx',
|
|
48
|
+
features: ['all'] // or specific: ['shaderSurface', 'rotationLock', 'events']
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Premium modules are now active
|
|
52
|
+
premium.shaderSurface.setParameter('projectionType', 1);
|
|
53
|
+
premium.rotationLock.setFlightMode(true);
|
|
54
|
+
premium.events.addTrigger('bass_drop', { ... });
|
|
55
|
+
premium.cssBridge.start({ target: document.documentElement });
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Public API Surface
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
// enablePremium() returns:
|
|
62
|
+
{
|
|
63
|
+
shaderSurface: ShaderParameterSurface,
|
|
64
|
+
rotationLock: RotationLockSystem,
|
|
65
|
+
layerGeometry: LayerGeometryMixer,
|
|
66
|
+
events: VisualEventSystem,
|
|
67
|
+
cssBridge: CSSBridge,
|
|
68
|
+
choreography: ChoreographyExtensions,
|
|
69
|
+
frameworkSync: FrameworkSync,
|
|
70
|
+
mcp: PremiumMCPServer,
|
|
71
|
+
destroy(): void
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Module 1: ShaderParameterSurface
|
|
78
|
+
|
|
79
|
+
**File**: `src/ShaderParameterSurface.js`
|
|
80
|
+
**Purpose**: Exposes 8 hardcoded shader values as controllable parameters.
|
|
81
|
+
|
|
82
|
+
### What's Currently Hardcoded (from shader analysis)
|
|
83
|
+
|
|
84
|
+
| Value | Where in GLSL | Current Value | Why It Should Be a Parameter |
|
|
85
|
+
|-------|--------------|---------------|------------------------------|
|
|
86
|
+
| Projection distance | `float w = 2.5 / (2.5 + p.w)` | 2.5 | `u_dimension` is supposed to control this but doesn't. This fix alone unlocks the `dimension` parameter |
|
|
87
|
+
| Projection type | Only perspective exists | 0 | Stereographic (`xyz / (1-w)`) and orthographic (`xyz`) are documented in CLAUDE.md but never implemented |
|
|
88
|
+
| UV scale | `uv * 3.0` | 3.0 | Controls zoom into 4D space. Different scales reveal different pattern features |
|
|
89
|
+
| Smoothstep threshold | `smoothstep(0.03, 0.04, ...)` | ~0.03 | Controls wireframe line thickness. Dramatic visual difference between 0.005 and 0.15 |
|
|
90
|
+
| Chaos noise frequencies | `sin(x*7)*cos(y*11)*sin(z*13)` | (7, 11, 13) | Different prime triples create different noise textures |
|
|
91
|
+
| Breath modulation strength | `1.0 + breath * 0.3` / `0.4` / `0.5` | Varies per system | Should be unified and controllable |
|
|
92
|
+
| Holographic auto-rotation speeds | `time * 0.1`, `0.12`, `0.08`, `0.2`, `0.15`, `0.25` | Per-axis | Currently only Holographic has auto-rotation; these speeds are hardcoded |
|
|
93
|
+
| Quantum particle size | `step(0.2, ...)` / `step(0.1, ...)` | 0.2 / 0.1 per layer | Controls particle dot size in Quantum system |
|
|
94
|
+
|
|
95
|
+
### API
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
class ShaderParameterSurface {
|
|
99
|
+
constructor(engine) { }
|
|
100
|
+
|
|
101
|
+
// Set a shader parameter (validates range, forwards to active system)
|
|
102
|
+
setParameter(name, value): void
|
|
103
|
+
getParameter(name): number | number[]
|
|
104
|
+
getParameterSchema(): Object // JSON Schema for all shader params
|
|
105
|
+
|
|
106
|
+
// Batch set
|
|
107
|
+
setParameters(params: Object): void
|
|
108
|
+
|
|
109
|
+
// Reset to defaults
|
|
110
|
+
reset(): void
|
|
111
|
+
|
|
112
|
+
// Supported parameters:
|
|
113
|
+
// 'projectionType' - int 0-2 (perspective/stereographic/orthographic)
|
|
114
|
+
// 'uvScale' - float 1.0-8.0
|
|
115
|
+
// 'lineThickness' - float 0.005-0.15
|
|
116
|
+
// 'noiseFrequency' - [float, float, float] each 1-50
|
|
117
|
+
// 'breathStrength' - float 0-1
|
|
118
|
+
// 'autoRotationSpeed' - [float x6] each 0-0.5 (XY,XZ,YZ,XW,YW,ZW)
|
|
119
|
+
// 'particleSize' - float 0.02-0.5
|
|
120
|
+
// 'layerAlpha' - { background, shadow, content, highlight, accent } each 0-1
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Implementation Strategy
|
|
125
|
+
|
|
126
|
+
This module wraps `engine.onParameterChange()` to intercept render updates. When a shader parameter is set, it modifies the GLSL shader strings dynamically (replacing hardcoded values with the new values) or — more practically — patches the system's `_buildUniforms()` method to include the new uniforms.
|
|
127
|
+
|
|
128
|
+
**Approach A (preferred)**: Add uniform declarations to each system's shader source. The shader code already has `#define`-like patterns we can augment. Add `uniform float u_uvScale;`, etc. and change `uv * 3.0` to `uv * u_uvScale`. This requires modifying the free SDK's shader strings — we'd submit PRs upstream for the uniform declarations (keeping defaults identical) and the premium module sends the actual values.
|
|
129
|
+
|
|
130
|
+
**Approach B (no-upstream-change)**: Use WebGL `uniform` injection post-compilation. After the free SDK compiles its shader, premium locates the uniform locations and sets them. This only works for uniforms already declared — so it doesn't help with adding NEW uniforms. Less clean but zero upstream changes.
|
|
131
|
+
|
|
132
|
+
**Recommended**: Approach A. Submit a PR to the free SDK that adds the uniform declarations with default values matching the current hardcoded values. This is a **no-behavior-change** PR. Then the premium module sends the actual configurable values.
|
|
133
|
+
|
|
134
|
+
### MCP Tool
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
{
|
|
138
|
+
name: 'set_shader_parameter',
|
|
139
|
+
description: 'Set fine-grained shader parameters (premium)',
|
|
140
|
+
inputSchema: {
|
|
141
|
+
type: 'object',
|
|
142
|
+
properties: {
|
|
143
|
+
projectionType: { type: 'integer', minimum: 0, maximum: 2 },
|
|
144
|
+
uvScale: { type: 'number', minimum: 1.0, maximum: 8.0 },
|
|
145
|
+
lineThickness: { type: 'number', minimum: 0.005, maximum: 0.15 },
|
|
146
|
+
noiseFrequency: { type: 'array', items: { type: 'number' }, minItems: 3, maxItems: 3 },
|
|
147
|
+
breathStrength: { type: 'number', minimum: 0, maximum: 1 },
|
|
148
|
+
autoRotationSpeed: { type: 'array', items: { type: 'number' }, minItems: 6, maxItems: 6 },
|
|
149
|
+
particleSize: { type: 'number', minimum: 0.02, maximum: 0.5 },
|
|
150
|
+
layerAlpha: { type: 'object' }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Module 2: RotationLockSystem
|
|
159
|
+
|
|
160
|
+
**File**: `src/RotationLockSystem.js`
|
|
161
|
+
**Purpose**: Lock rotation axes at fixed values and provide "flight mode" — stable screen orientation while 4D content streams past.
|
|
162
|
+
|
|
163
|
+
### Why This Matters
|
|
164
|
+
|
|
165
|
+
When an agent animates `rot4dXW` to create a "portal" effect, other inputs (audio reactivity, spatial input, user interaction) can also change `rot4dXY`/`rot4dXZ`/`rot4dYZ`, causing the screen-plane orientation to drift. Axis locking prevents this — the portal effect stays clean.
|
|
166
|
+
|
|
167
|
+
"Flight mode" is a preset: lock all 3D rotations (XY/XZ/YZ) at their current values, leaving 4D rotations (XW/YW/ZW) free. The result: the viewport is stable, and 4D geometry "flies through" it as hyperspace rotations are animated.
|
|
168
|
+
|
|
169
|
+
### API
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
class RotationLockSystem {
|
|
173
|
+
constructor(engine) { }
|
|
174
|
+
|
|
175
|
+
// Lock a specific axis at current value or specified value
|
|
176
|
+
lockAxis(axisName: string, value?: number): void
|
|
177
|
+
// axisName: 'rot4dXY' | 'rot4dXZ' | 'rot4dYZ' | 'rot4dXW' | 'rot4dYW' | 'rot4dZW'
|
|
178
|
+
|
|
179
|
+
// Unlock a specific axis
|
|
180
|
+
unlockAxis(axisName: string): void
|
|
181
|
+
|
|
182
|
+
// Lock all 3D rotations, free all 4D rotations
|
|
183
|
+
setFlightMode(enabled: boolean): void
|
|
184
|
+
|
|
185
|
+
// Get lock state
|
|
186
|
+
isLocked(axisName: string): boolean
|
|
187
|
+
getLockedValue(axisName: string): number | null
|
|
188
|
+
getLockedAxes(): string[]
|
|
189
|
+
|
|
190
|
+
// Convenience: lock all axes
|
|
191
|
+
lockAll(values?: Object): void
|
|
192
|
+
unlockAll(): void
|
|
193
|
+
|
|
194
|
+
destroy(): void
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Implementation
|
|
199
|
+
|
|
200
|
+
Intercepts `engine.setParameter()` by wrapping it:
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
const originalSetParameter = engine.setParameter.bind(engine);
|
|
204
|
+
engine.setParameter = (name, value) => {
|
|
205
|
+
if (this._locks.has(name)) {
|
|
206
|
+
// Silently ignore — axis is locked
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
originalSetParameter(name, value);
|
|
210
|
+
};
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Also intercepts `engine.updateCurrentSystemParameters()` to enforce locked values:
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
const originalUpdate = engine.updateCurrentSystemParameters.bind(engine);
|
|
217
|
+
engine.updateCurrentSystemParameters = () => {
|
|
218
|
+
// Override locked axes in the parameter manager before update
|
|
219
|
+
for (const [axis, lockedValue] of this._locks) {
|
|
220
|
+
engine.parameters.setParameter(axis, lockedValue);
|
|
221
|
+
}
|
|
222
|
+
originalUpdate();
|
|
223
|
+
};
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### MCP Tool
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
{
|
|
230
|
+
name: 'set_rotation_lock',
|
|
231
|
+
description: 'Lock or unlock rotation axes. Use flight mode to lock 3D rotations while 4D rotates freely (premium)',
|
|
232
|
+
inputSchema: {
|
|
233
|
+
type: 'object',
|
|
234
|
+
properties: {
|
|
235
|
+
axes: { type: 'array', items: { type: 'string' } },
|
|
236
|
+
locked: { type: 'boolean' },
|
|
237
|
+
values: { type: 'array', items: { type: 'number' } },
|
|
238
|
+
flightMode: { type: 'boolean' }
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Module 3: LayerGeometryMixer
|
|
247
|
+
|
|
248
|
+
**File**: `src/LayerGeometryMixer.js`
|
|
249
|
+
**Purpose**: Allow each of the 5 layers to render a different geometry.
|
|
250
|
+
|
|
251
|
+
### Current Limitation
|
|
252
|
+
|
|
253
|
+
Geometry is global: `engine.setParameter('geometry', 16)` sets all layers to geometry 16. The LayerRelationshipGraph relationship functions pass `geometry` through unchanged — none of the 6 preset relationship types (echo, mirror, complement, harmonic, reactive, chase) modify the `geometry` key.
|
|
254
|
+
|
|
255
|
+
### How It Works
|
|
256
|
+
|
|
257
|
+
The shader uniform `u_geometry` (float) is already sent per-visualizer-instance. Each HolographicVisualizer/QuantumVisualizer instance has its own WebGL context with its own uniform state. So geometrically, per-layer geometry IS possible — we just need to get different geometry values into each layer's resolved parameters.
|
|
258
|
+
|
|
259
|
+
**Approach**: Register custom relationship functions on the LayerRelationshipGraph that override the `geometry` key:
|
|
260
|
+
|
|
261
|
+
```javascript
|
|
262
|
+
// Custom relationship that offsets geometry
|
|
263
|
+
engine.activeSystem.layerGraph.setRelationship('shadow', (kp, time) => ({
|
|
264
|
+
...kp,
|
|
265
|
+
geometry: (kp.geometry + 8) % 24 // Same base shape, next warp type
|
|
266
|
+
}));
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The LayerGeometryMixer wraps this into a clean API.
|
|
270
|
+
|
|
271
|
+
### Verification Needed
|
|
272
|
+
|
|
273
|
+
Before implementation, verify that `RealHolographicSystem.updateParameters()` doesn't override per-layer geometry with the global value. The research suggests it builds a single `currentVariant` and calls `generateVariantParams(variant)` for all layers — this may need patching.
|
|
274
|
+
|
|
275
|
+
### API
|
|
276
|
+
|
|
277
|
+
```javascript
|
|
278
|
+
class LayerGeometryMixer {
|
|
279
|
+
constructor(engine) { }
|
|
280
|
+
|
|
281
|
+
// Set explicit geometry for a layer
|
|
282
|
+
setLayerGeometry(layerName: string, geometry: number): void
|
|
283
|
+
|
|
284
|
+
// Use geometry offset from keystone (same base, different warp)
|
|
285
|
+
setGeometryOffset(layerName: string, offset: number): void
|
|
286
|
+
|
|
287
|
+
// Clear per-layer geometry (revert to keystone geometry)
|
|
288
|
+
clearLayerGeometry(layerName: string): void
|
|
289
|
+
|
|
290
|
+
// Get current per-layer geometries
|
|
291
|
+
getLayerGeometries(): { background: number, shadow: number, content: number, highlight: number, accent: number }
|
|
292
|
+
|
|
293
|
+
destroy(): void
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### New Relationship Presets
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
// Added to LayerRelationshipGraph preset library:
|
|
301
|
+
function geometryOffset(config = {}) {
|
|
302
|
+
const { offset = 8, ...echoConfig } = config;
|
|
303
|
+
const echoFn = echo(echoConfig);
|
|
304
|
+
return (kp, time) => ({
|
|
305
|
+
...echoFn(kp, time),
|
|
306
|
+
geometry: ((kp.geometry || 0) + offset) % 24
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function geometrySplit(config = {}) {
|
|
311
|
+
// Explicit per-layer geometry assignment
|
|
312
|
+
return (kp, time) => ({
|
|
313
|
+
...kp,
|
|
314
|
+
geometry: config.geometry ?? kp.geometry
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### MCP Tool
|
|
320
|
+
|
|
321
|
+
```javascript
|
|
322
|
+
{
|
|
323
|
+
name: 'set_layer_geometry',
|
|
324
|
+
description: 'Set geometry per layer. Each layer can render a different geometry variant (premium)',
|
|
325
|
+
inputSchema: {
|
|
326
|
+
type: 'object',
|
|
327
|
+
properties: {
|
|
328
|
+
layer: { type: 'string', enum: ['background', 'shadow', 'content', 'highlight', 'accent'] },
|
|
329
|
+
geometry: { type: 'integer', minimum: 0, maximum: 23 },
|
|
330
|
+
offset: { type: 'integer', minimum: -23, maximum: 23 }
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Module 4: VisualEventSystem
|
|
339
|
+
|
|
340
|
+
**File**: `src/VisualEventSystem.js`
|
|
341
|
+
**Purpose**: Threshold-based triggers that fire discrete state changes — not continuous parameter mappings. "When X happens, DO Y."
|
|
342
|
+
|
|
343
|
+
### Why This Matters
|
|
344
|
+
|
|
345
|
+
The free SDK has continuous reactivity (audio→parameter mapping via ReactivityManager) and timed animation (TransitionAnimator, ParameterTimeline, ChoreographyPlayer). But there's no way to say "when bass exceeds 0.8, switch to storm profile for 3 seconds." That's an EVENT — a discrete state change with a trigger, an action, and optionally a revert.
|
|
346
|
+
|
|
347
|
+
This is what makes VIB3+ feel intentional rather than random. Without events, audio reactivity just produces continuous wobble. WITH events, a bass drop can trigger a dramatic visual state change.
|
|
348
|
+
|
|
349
|
+
### API
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
class VisualEventSystem {
|
|
353
|
+
constructor(engine, premium) { }
|
|
354
|
+
|
|
355
|
+
// Add a trigger
|
|
356
|
+
addTrigger(id: string, config: TriggerConfig): void
|
|
357
|
+
|
|
358
|
+
// Remove a trigger
|
|
359
|
+
removeTrigger(id: string): void
|
|
360
|
+
|
|
361
|
+
// List all triggers
|
|
362
|
+
listTriggers(): TriggerConfig[]
|
|
363
|
+
|
|
364
|
+
// Emit a custom event (for external code to trigger actions)
|
|
365
|
+
emit(eventName: string, data?: Object): void
|
|
366
|
+
|
|
367
|
+
// Subscribe to trigger fires
|
|
368
|
+
on(eventName: string, callback: Function): () => void // returns unsubscribe
|
|
369
|
+
|
|
370
|
+
// Enable/disable
|
|
371
|
+
setEnabled(enabled: boolean): void
|
|
372
|
+
|
|
373
|
+
destroy(): void
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// TriggerConfig:
|
|
377
|
+
{
|
|
378
|
+
source: string, // 'parameter.chaos' | 'audio.bass' | 'audio.mid' | 'audio.high' | 'audio.energy' | 'custom.eventName'
|
|
379
|
+
condition: string, // 'exceeds' | 'drops_below' | 'crosses' | 'equals'
|
|
380
|
+
threshold: number,
|
|
381
|
+
cooldown: number, // ms before trigger can fire again (default: 1000)
|
|
382
|
+
action: {
|
|
383
|
+
type: string, // 'layer_profile' | 'color_preset' | 'set_parameters' | 'transition' | 'custom'
|
|
384
|
+
value: any, // profile name, preset name, params object, or custom handler
|
|
385
|
+
duration?: number, // ms to hold the action state (optional)
|
|
386
|
+
revertTo?: any, // what to revert to after duration (optional)
|
|
387
|
+
easing?: string, // for transitions
|
|
388
|
+
transition?: boolean // smooth transition to the new state
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Implementation
|
|
394
|
+
|
|
395
|
+
Uses `engine.onParameterChange()` to watch parameter sources. Uses audio input via `engine.reactivity` events or direct audio polling for audio sources.
|
|
396
|
+
|
|
397
|
+
Each frame:
|
|
398
|
+
1. Read current values for all watched sources
|
|
399
|
+
2. Evaluate trigger conditions against thresholds
|
|
400
|
+
3. Check cooldown timers
|
|
401
|
+
4. Fire actions for triggered events
|
|
402
|
+
5. Check duration timers for active timed actions
|
|
403
|
+
6. Revert expired timed actions
|
|
404
|
+
|
|
405
|
+
### Example Patterns
|
|
406
|
+
|
|
407
|
+
```javascript
|
|
408
|
+
// Bass drop triggers storm mode
|
|
409
|
+
events.addTrigger('bass_storm', {
|
|
410
|
+
source: 'audio.bass',
|
|
411
|
+
condition: 'exceeds',
|
|
412
|
+
threshold: 0.8,
|
|
413
|
+
cooldown: 3000,
|
|
414
|
+
action: {
|
|
415
|
+
type: 'layer_profile',
|
|
416
|
+
value: 'storm',
|
|
417
|
+
duration: 2000,
|
|
418
|
+
revertTo: 'holographic'
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
// High chaos triggers red alert color
|
|
423
|
+
events.addTrigger('chaos_alert', {
|
|
424
|
+
source: 'parameter.chaos',
|
|
425
|
+
condition: 'exceeds',
|
|
426
|
+
threshold: 0.7,
|
|
427
|
+
cooldown: 5000,
|
|
428
|
+
action: {
|
|
429
|
+
type: 'set_parameters',
|
|
430
|
+
value: { hue: 0, saturation: 1, intensity: 1 },
|
|
431
|
+
duration: 1500,
|
|
432
|
+
easing: 'elastic',
|
|
433
|
+
transition: true
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// Geometry reaches hypertetra range → cosmic color preset
|
|
438
|
+
events.addTrigger('hypertetra_cosmic', {
|
|
439
|
+
source: 'parameter.geometry',
|
|
440
|
+
condition: 'exceeds',
|
|
441
|
+
threshold: 15.5, // entering 16+ range
|
|
442
|
+
cooldown: 0, // fires every time
|
|
443
|
+
action: {
|
|
444
|
+
type: 'color_preset',
|
|
445
|
+
value: 'Cosmic Nebula',
|
|
446
|
+
transition: true
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// Custom event from external code
|
|
451
|
+
events.addTrigger('card_flip', {
|
|
452
|
+
source: 'custom.card_flip',
|
|
453
|
+
condition: 'equals',
|
|
454
|
+
threshold: 1,
|
|
455
|
+
cooldown: 500,
|
|
456
|
+
action: {
|
|
457
|
+
type: 'transition',
|
|
458
|
+
value: { rot4dXW: 0.9, gridDensity: 12 },
|
|
459
|
+
easing: 'easeOutQuad',
|
|
460
|
+
duration: 800
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### MCP Tools
|
|
466
|
+
|
|
467
|
+
```javascript
|
|
468
|
+
// add_visual_trigger
|
|
469
|
+
{
|
|
470
|
+
name: 'add_visual_trigger',
|
|
471
|
+
description: 'Add a threshold-based event trigger (premium)',
|
|
472
|
+
inputSchema: {
|
|
473
|
+
type: 'object',
|
|
474
|
+
required: ['id', 'source', 'condition', 'threshold', 'action'],
|
|
475
|
+
properties: {
|
|
476
|
+
id: { type: 'string' },
|
|
477
|
+
source: { type: 'string' },
|
|
478
|
+
condition: { type: 'string', enum: ['exceeds', 'drops_below', 'crosses', 'equals'] },
|
|
479
|
+
threshold: { type: 'number' },
|
|
480
|
+
cooldown: { type: 'number' },
|
|
481
|
+
action: { type: 'object' }
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// remove_visual_trigger
|
|
487
|
+
{
|
|
488
|
+
name: 'remove_visual_trigger',
|
|
489
|
+
description: 'Remove a visual event trigger by ID (premium)',
|
|
490
|
+
inputSchema: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } }
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// list_visual_triggers
|
|
494
|
+
{
|
|
495
|
+
name: 'list_visual_triggers',
|
|
496
|
+
description: 'List all active visual event triggers (premium)',
|
|
497
|
+
inputSchema: { type: 'object', properties: {} }
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## Module 5: CSSBridge
|
|
504
|
+
|
|
505
|
+
**File**: `src/CSSBridge.js`
|
|
506
|
+
**Purpose**: Live bidirectional binding between VIB3+ parameters and CSS custom properties.
|
|
507
|
+
|
|
508
|
+
### Why This Matters
|
|
509
|
+
|
|
510
|
+
CSS animations, transforms, and layout properties can express things WebGL cannot: text, DOM elements, box shadows, blur filters, clip paths. When VIB3+ parameter state drives CSS custom properties in real-time, the ENTIRE page becomes part of the visualization — not just the canvas rectangles.
|
|
511
|
+
|
|
512
|
+
Conversely, CSS animations (scroll position, hover states, transition values) can drive VIB3+ parameters, creating page interactions that directly control the 4D visualization.
|
|
513
|
+
|
|
514
|
+
### API
|
|
515
|
+
|
|
516
|
+
```javascript
|
|
517
|
+
class CSSBridge {
|
|
518
|
+
constructor(engine) { }
|
|
519
|
+
|
|
520
|
+
// Start the bridge
|
|
521
|
+
start(options?: CSSBridgeOptions): void
|
|
522
|
+
|
|
523
|
+
// Stop the bridge
|
|
524
|
+
stop(): void
|
|
525
|
+
|
|
526
|
+
// Manually push a parameter value to CSS
|
|
527
|
+
pushToCSS(name: string, value: number): void
|
|
528
|
+
|
|
529
|
+
// Manually read a CSS custom property and push to engine
|
|
530
|
+
pullFromCSS(name: string): number
|
|
531
|
+
|
|
532
|
+
// Check if running
|
|
533
|
+
isActive(): boolean
|
|
534
|
+
|
|
535
|
+
destroy(): void
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// CSSBridgeOptions:
|
|
539
|
+
{
|
|
540
|
+
target: HTMLElement, // default: document.documentElement
|
|
541
|
+
prefix: string, // default: 'vib3' (produces --vib3-hue, etc.)
|
|
542
|
+
outbound: boolean, // default: true (engine → CSS)
|
|
543
|
+
inbound: boolean, // default: false (CSS → engine)
|
|
544
|
+
throttle: number, // default: 16 (ms, ~60fps)
|
|
545
|
+
parameters: string[], // which params to bridge. default: all
|
|
546
|
+
inboundParameters: string[], // which CSS vars to watch for inbound. default: none
|
|
547
|
+
normalize: boolean // default: true (normalize ranges to 0-1 for CSS)
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### Outbound (VIB3+ → CSS)
|
|
552
|
+
|
|
553
|
+
Subscribes to `engine.onParameterChange()`. On each update (throttled):
|
|
554
|
+
|
|
555
|
+
```javascript
|
|
556
|
+
for (const param of this.parameters) {
|
|
557
|
+
const value = params[param];
|
|
558
|
+
const cssName = `--${this.prefix}-${this.kebabCase(param)}`;
|
|
559
|
+
|
|
560
|
+
if (this.normalize) {
|
|
561
|
+
// Normalize to 0-1 range for easier CSS calc()
|
|
562
|
+
const { min, max } = this.paramRanges[param];
|
|
563
|
+
const normalized = (value - min) / (max - min);
|
|
564
|
+
this.target.style.setProperty(cssName, normalized);
|
|
565
|
+
this.target.style.setProperty(`${cssName}-raw`, value);
|
|
566
|
+
} else {
|
|
567
|
+
this.target.style.setProperty(cssName, value);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
**CSS output example** (with `normalize: true`):
|
|
573
|
+
```css
|
|
574
|
+
:root {
|
|
575
|
+
--vib3-hue: 0.611; /* 220/360 normalized */
|
|
576
|
+
--vib3-hue-raw: 220; /* raw value */
|
|
577
|
+
--vib3-grid-density: 0.375; /* (40-4)/(100-4) normalized */
|
|
578
|
+
--vib3-grid-density-raw: 40;
|
|
579
|
+
--vib3-rot4d-xw: 0.225; /* (0.9-(-2))/(2-(-2)) normalized */
|
|
580
|
+
--vib3-rot4d-xw-raw: 0.9;
|
|
581
|
+
--vib3-chaos: 0.1; /* already 0-1 range */
|
|
582
|
+
--vib3-chaos-raw: 0.1;
|
|
583
|
+
--vib3-intensity: 0.7;
|
|
584
|
+
--vib3-intensity-raw: 0.7;
|
|
585
|
+
}
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
**CSS usage examples:**
|
|
589
|
+
```css
|
|
590
|
+
/* Card tilt follows 4D rotation */
|
|
591
|
+
.card {
|
|
592
|
+
transform: perspective(800px)
|
|
593
|
+
rotateY(calc(var(--vib3-rot4d-xw) * 30deg - 15deg));
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/* Shadow grows with grid density decrease (lower density = more shadow) */
|
|
597
|
+
.card-shadow {
|
|
598
|
+
box-shadow: 0
|
|
599
|
+
calc((1 - var(--vib3-grid-density)) * 24px)
|
|
600
|
+
calc((1 - var(--vib3-grid-density)) * 40px)
|
|
601
|
+
rgba(0, 0, 0, calc(0.1 + var(--vib3-intensity) * 0.3));
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/* Background blur follows chaos */
|
|
605
|
+
.background {
|
|
606
|
+
filter: blur(calc(var(--vib3-chaos) * 20px));
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/* Text color from VIB3+ hue */
|
|
610
|
+
.title {
|
|
611
|
+
color: hsl(calc(var(--vib3-hue-raw) * 1deg), 80%, 65%);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/* Clip path deforms with chaos */
|
|
615
|
+
.blob {
|
|
616
|
+
border-radius: calc(30% + var(--vib3-chaos) * 20%);
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### Inbound (CSS → VIB3+)
|
|
621
|
+
|
|
622
|
+
Uses `requestAnimationFrame` polling (MutationObserver doesn't fire for CSS custom property changes from animations):
|
|
623
|
+
|
|
624
|
+
```javascript
|
|
625
|
+
function pollCSSProperties() {
|
|
626
|
+
for (const cssParam of this.inboundParameters) {
|
|
627
|
+
const cssName = `--${this.prefix}-input-${this.kebabCase(cssParam)}`;
|
|
628
|
+
const raw = getComputedStyle(this.target).getPropertyValue(cssName);
|
|
629
|
+
const value = parseFloat(raw);
|
|
630
|
+
if (!isNaN(value) && value !== this._lastInbound[cssParam]) {
|
|
631
|
+
this._lastInbound[cssParam] = value;
|
|
632
|
+
engine.setParameter(cssParam, this.denormalize(cssParam, value));
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
if (this._active) requestAnimationFrame(pollCSSProperties);
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
**CSS input example:**
|
|
640
|
+
```css
|
|
641
|
+
/* Scroll drives 4D rotation via CSS custom property */
|
|
642
|
+
:root {
|
|
643
|
+
--vib3-input-rot4d-xw: 0;
|
|
644
|
+
}
|
|
645
|
+
@keyframes scroll-drive {
|
|
646
|
+
from { --vib3-input-rot4d-xw: 0; }
|
|
647
|
+
to { --vib3-input-rot4d-xw: 1; }
|
|
648
|
+
}
|
|
649
|
+
html {
|
|
650
|
+
animation: scroll-drive linear;
|
|
651
|
+
animation-timeline: scroll(root);
|
|
652
|
+
}
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
### MCP Tool
|
|
656
|
+
|
|
657
|
+
```javascript
|
|
658
|
+
{
|
|
659
|
+
name: 'configure_css_bridge',
|
|
660
|
+
description: 'Configure live CSS custom property binding (premium)',
|
|
661
|
+
inputSchema: {
|
|
662
|
+
type: 'object',
|
|
663
|
+
properties: {
|
|
664
|
+
enabled: { type: 'boolean' },
|
|
665
|
+
outbound: { type: 'boolean' },
|
|
666
|
+
inbound: { type: 'boolean' },
|
|
667
|
+
parameters: { type: 'array', items: { type: 'string' } },
|
|
668
|
+
throttle: { type: 'number' },
|
|
669
|
+
normalize: { type: 'boolean' }
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
---
|
|
676
|
+
|
|
677
|
+
## Module 6: ChoreographyExtensions
|
|
678
|
+
|
|
679
|
+
**File**: `src/ChoreographyExtensions.js`
|
|
680
|
+
**Purpose**: Extend ChoreographyPlayer scenes with `layer_profile` and `layer_overrides` fields.
|
|
681
|
+
|
|
682
|
+
### Current Limitation
|
|
683
|
+
|
|
684
|
+
`ChoreographyScene` in the free SDK supports: `system`, `geometry`, `transition_in`, `tracks`, `color_preset`, `post_processing`, `audio`. It does NOT support: `layer_profile`, `layer_overrides`, `triggers`.
|
|
685
|
+
|
|
686
|
+
### Extended Scene Format
|
|
687
|
+
|
|
688
|
+
```javascript
|
|
689
|
+
{
|
|
690
|
+
// Existing fields (free SDK):
|
|
691
|
+
system: 'holographic',
|
|
692
|
+
geometry: 16,
|
|
693
|
+
transition_in: { type: 'smooth', duration: 800 },
|
|
694
|
+
tracks: {
|
|
695
|
+
gridDensity: [
|
|
696
|
+
{ time: 0, value: 40 },
|
|
697
|
+
{ time: 0.5, value: 14, easing: 'easeOutQuad' },
|
|
698
|
+
{ time: 1, value: 28, easing: 'easeOut' }
|
|
699
|
+
]
|
|
700
|
+
},
|
|
701
|
+
color_preset: 'Cosmic Nebula',
|
|
702
|
+
|
|
703
|
+
// NEW premium fields:
|
|
704
|
+
layer_profile: 'storm',
|
|
705
|
+
layer_overrides: {
|
|
706
|
+
shadow: { type: 'echo', config: { densityScale: 1.5 } },
|
|
707
|
+
accent: { type: 'reactive', config: { gain: 4.0, decay: 0.85 } }
|
|
708
|
+
},
|
|
709
|
+
triggers: [
|
|
710
|
+
{
|
|
711
|
+
source: 'audio.bass',
|
|
712
|
+
condition: 'exceeds',
|
|
713
|
+
threshold: 0.8,
|
|
714
|
+
action: { type: 'layer_profile', value: 'storm', duration: 2000, revertTo: 'holographic' }
|
|
715
|
+
}
|
|
716
|
+
],
|
|
717
|
+
rotation_locks: {
|
|
718
|
+
rot4dXY: 0,
|
|
719
|
+
rot4dXZ: 0,
|
|
720
|
+
rot4dYZ: 0
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
### Implementation
|
|
726
|
+
|
|
727
|
+
Wraps `ChoreographyPlayer._enterScene()` by monkey-patching or using the `onSceneChange` callback:
|
|
728
|
+
|
|
729
|
+
```javascript
|
|
730
|
+
class ChoreographyExtensions {
|
|
731
|
+
constructor(engine, premium, choreographyPlayer) {
|
|
732
|
+
choreographyPlayer.onSceneChange = (index, scene) => {
|
|
733
|
+
// Apply layer profile
|
|
734
|
+
if (scene.layer_profile && engine.activeSystem?.loadRelationshipProfile) {
|
|
735
|
+
engine.activeSystem.loadRelationshipProfile(scene.layer_profile);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Apply layer overrides
|
|
739
|
+
if (scene.layer_overrides && engine.activeSystem?.layerGraph) {
|
|
740
|
+
for (const [layer, config] of Object.entries(scene.layer_overrides)) {
|
|
741
|
+
engine.activeSystem.layerGraph.setRelationship(layer, config.type, config.config);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// Register scene triggers
|
|
746
|
+
if (scene.triggers && premium.events) {
|
|
747
|
+
// Clear previous scene's triggers
|
|
748
|
+
premium.events.clearSceneTriggers();
|
|
749
|
+
for (const trigger of scene.triggers) {
|
|
750
|
+
premium.events.addTrigger(`scene_${index}_${trigger.source}`, trigger);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// Apply rotation locks
|
|
755
|
+
if (scene.rotation_locks && premium.rotationLock) {
|
|
756
|
+
premium.rotationLock.unlockAll();
|
|
757
|
+
for (const [axis, value] of Object.entries(scene.rotation_locks)) {
|
|
758
|
+
premium.rotationLock.lockAxis(axis, value);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
---
|
|
767
|
+
|
|
768
|
+
## Module 7: FrameworkSync
|
|
769
|
+
|
|
770
|
+
**File**: `src/FrameworkSync.js`
|
|
771
|
+
**Purpose**: Bidirectional state sync between VIB3+ engine and React/Vue/Svelte frameworks.
|
|
772
|
+
|
|
773
|
+
### Current Limitation
|
|
774
|
+
|
|
775
|
+
The free SDK's framework integrations (Vib3React.js, Vib3Vue.js, Vib3Svelte.js) generate code that pushes props→engine but never subscribes to engine→framework state. If audio reactivity or spatial input changes a parameter, the framework state goes stale.
|
|
776
|
+
|
|
777
|
+
### Implementation
|
|
778
|
+
|
|
779
|
+
Generates enhanced framework code that includes `onParameterChange()` subscription:
|
|
780
|
+
|
|
781
|
+
**React (enhanced `useVib3()`):**
|
|
782
|
+
```javascript
|
|
783
|
+
useEffect(() => {
|
|
784
|
+
if (!engine) return;
|
|
785
|
+
const unsubscribe = engine.onParameterChange((params) => {
|
|
786
|
+
setParameters(prev => {
|
|
787
|
+
// Only update if values actually changed (avoid infinite loops)
|
|
788
|
+
const changed = Object.keys(params).some(k => prev[k] !== params[k]);
|
|
789
|
+
return changed ? { ...prev, ...params } : prev;
|
|
790
|
+
});
|
|
791
|
+
});
|
|
792
|
+
return unsubscribe;
|
|
793
|
+
}, [engine]);
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
**Vue (enhanced composable):**
|
|
797
|
+
```javascript
|
|
798
|
+
watch(engine, (eng) => {
|
|
799
|
+
if (!eng) return;
|
|
800
|
+
eng.onParameterChange((params) => {
|
|
801
|
+
Object.assign(parameters, params);
|
|
802
|
+
});
|
|
803
|
+
});
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
**Svelte (enhanced store):**
|
|
807
|
+
```javascript
|
|
808
|
+
// In vib3Actions.initialize():
|
|
809
|
+
engine.onParameterChange((params) => {
|
|
810
|
+
vib3Store.update(state => ({
|
|
811
|
+
...state,
|
|
812
|
+
parameters: { ...state.parameters, ...params }
|
|
813
|
+
}));
|
|
814
|
+
});
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
---
|
|
818
|
+
|
|
819
|
+
## Module 8: PremiumMCPServer
|
|
820
|
+
|
|
821
|
+
**File**: `src/mcp/PremiumMCPServer.js`
|
|
822
|
+
**Purpose**: Wraps the free SDK's MCPServer, adding premium tool handling with license validation.
|
|
823
|
+
|
|
824
|
+
### Tool List
|
|
825
|
+
|
|
826
|
+
| Tool | Module | Description |
|
|
827
|
+
|------|--------|-------------|
|
|
828
|
+
| `set_shader_parameter` | ShaderParameterSurface | Set fine-grained shader params |
|
|
829
|
+
| `set_rotation_lock` | RotationLockSystem | Lock/unlock rotation axes, flight mode |
|
|
830
|
+
| `set_layer_geometry` | LayerGeometryMixer | Per-layer geometry assignment |
|
|
831
|
+
| `add_visual_trigger` | VisualEventSystem | Add threshold-based event trigger |
|
|
832
|
+
| `remove_visual_trigger` | VisualEventSystem | Remove trigger by ID |
|
|
833
|
+
| `list_visual_triggers` | VisualEventSystem | List all active triggers |
|
|
834
|
+
| `configure_css_bridge` | CSSBridge | Configure live CSS binding |
|
|
835
|
+
| `create_premium_choreography` | ChoreographyExtensions | Create choreography with layer profiles + triggers |
|
|
836
|
+
|
|
837
|
+
### License Gating
|
|
838
|
+
|
|
839
|
+
```javascript
|
|
840
|
+
async handleToolCall(toolName, args) {
|
|
841
|
+
if (PREMIUM_TOOLS.has(toolName)) {
|
|
842
|
+
if (!this.premium || !this.premium.isLicensed()) {
|
|
843
|
+
return {
|
|
844
|
+
content: [{ type: 'text', text: `Tool "${toolName}" requires @vib3code/premium. See https://vib3.dev/premium` }],
|
|
845
|
+
isError: true
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
// Route to appropriate module handler
|
|
850
|
+
return this.routeTool(toolName, args);
|
|
851
|
+
}
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
---
|
|
855
|
+
|
|
856
|
+
## New Premium Repo File Structure
|
|
857
|
+
|
|
858
|
+
```
|
|
859
|
+
vib3-premium/
|
|
860
|
+
├── CLAUDE.md # Agent context for premium development
|
|
861
|
+
├── package.json # @vib3code/premium
|
|
862
|
+
├── vitest.config.js # Test config
|
|
863
|
+
├── src/
|
|
864
|
+
│ ├── index.js # enablePremium() entry point + license validation
|
|
865
|
+
│ ├── ShaderParameterSurface.js # Module 1
|
|
866
|
+
│ ├── RotationLockSystem.js # Module 2
|
|
867
|
+
│ ├── LayerGeometryMixer.js # Module 3
|
|
868
|
+
│ ├── VisualEventSystem.js # Module 4
|
|
869
|
+
│ ├── CSSBridge.js # Module 5
|
|
870
|
+
│ ├── ChoreographyExtensions.js # Module 6
|
|
871
|
+
│ ├── FrameworkSync.js # Module 7
|
|
872
|
+
│ └── mcp/
|
|
873
|
+
│ ├── premium-tools.js # Tool definitions
|
|
874
|
+
│ └── PremiumMCPServer.js # Module 8
|
|
875
|
+
├── DOCS/
|
|
876
|
+
│ ├── ARCHITECTURE.md # Extension architecture
|
|
877
|
+
│ ├── SHADER_PARAMETER_REFERENCE.md # Full parameter→shader→visual reference
|
|
878
|
+
│ ├── VISUAL_EVENT_PATTERNS.md # Trigger pattern library
|
|
879
|
+
│ ├── CSS_INTEGRATION_GUIDE.md # CSSBridge usage + CSS examples
|
|
880
|
+
│ └── AGENT_PREMIUM_CONTEXT.md # Agent onboarding for premium
|
|
881
|
+
├── examples/
|
|
882
|
+
│ ├── card-lift-portal.html # Gold standard: card lift + portal
|
|
883
|
+
│ ├── audio-storm.html # Audio events + layer storms
|
|
884
|
+
│ └── css-synchronized.html # CSSBridge + CSS coordination
|
|
885
|
+
└── tests/
|
|
886
|
+
├── shader-surface.test.js
|
|
887
|
+
├── rotation-lock.test.js
|
|
888
|
+
├── layer-geometry.test.js
|
|
889
|
+
├── visual-events.test.js
|
|
890
|
+
├── css-bridge.test.js
|
|
891
|
+
├── choreography-ext.test.js
|
|
892
|
+
└── framework-sync.test.js
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
---
|
|
896
|
+
|
|
897
|
+
## Free SDK Bug Fixes (Pre-requisites)
|
|
898
|
+
|
|
899
|
+
These bugs should be fixed in `@vib3code/sdk` before premium development starts. They are NOT premium features — they're broken standard behavior.
|
|
900
|
+
|
|
901
|
+
### Fix 1: `u_dimension` Projection (VERIFY POST-MERGE)
|
|
902
|
+
|
|
903
|
+
**File**: `src/faceted/FacetedSystem.js`, `src/quantum/QuantumVisualizer.js`, `src/holograms/HolographicVisualizer.js`
|
|
904
|
+
**What**: Replace `float w = 2.5 / (2.5 + p.w)` with `float w = u_dimension / (u_dimension + p.w)` in all `project4Dto3D()` functions
|
|
905
|
+
**Impact**: The `dimension` parameter actually controls 4D projection distance. Default 3.5 produces slightly different visual than current 2.5 — may need to adjust the default in `Parameters.js` to 2.5 for visual consistency.
|
|
906
|
+
**Verify**: The 6-commit dev branch (`claude/vib3-sdk-handoff-p00R8`) may have fixed this under "uniform standardization" — check before duplicating work.
|
|
907
|
+
|
|
908
|
+
### Fix 2: Dead Faceted Audio Code
|
|
909
|
+
|
|
910
|
+
**File**: `src/faceted/FacetedSystem.js`
|
|
911
|
+
**What**: In the fragment shader, `audioDensityMod` and `audioMorphMod` are computed from `u_bass` and `u_mid` but never used in the final value computation. Wire them:
|
|
912
|
+
```glsl
|
|
913
|
+
// Currently: float value = latticeFunction(...) * u_morphFactor;
|
|
914
|
+
// Should be: float value = latticeFunction(...) * u_morphFactor * audioMorphMod;
|
|
915
|
+
// And: gridSize = u_gridDensity * 0.08 * audioDensityMod;
|
|
916
|
+
```
|
|
917
|
+
**Impact**: Faceted system becomes audio-reactive (bass pulses density, mid modulates morph).
|
|
918
|
+
**Verify**: This is shader logic, not naming — unlikely to be covered by the dev branch fixes.
|
|
919
|
+
|
|
920
|
+
### Fix 3: Hue Encoding Inconsistency
|
|
921
|
+
|
|
922
|
+
**File**: `src/quantum/QuantumVisualizer.js` (or `src/faceted/FacetedSystem.js`)
|
|
923
|
+
**What**: Faceted passes hue as 0-360 raw degrees to the shader. Quantum normalizes to 0-1 before sending. Pick one convention.
|
|
924
|
+
**Recommendation**: Standardize to 0-360 in the parameter API (as defined in `Parameters.js`), normalize to 0-1 inside each system's `updateParameters()` if the shader needs it.
|
|
925
|
+
**Verify**: Check if "uniform standardization" commit addressed this.
|
|
926
|
+
|
|
927
|
+
---
|
|
928
|
+
|
|
929
|
+
## Upstream PRs to Free SDK (Enabling Premium)
|
|
930
|
+
|
|
931
|
+
These are optional enhancements to the free SDK that make premium integration cleaner:
|
|
932
|
+
|
|
933
|
+
### PR 1: Shader Uniform Declarations (No Behavior Change)
|
|
934
|
+
|
|
935
|
+
Add `uniform float u_uvScale;`, `uniform int u_projectionType;`, `uniform float u_lineThickness;` etc. to all shader strings, with default values matching current hardcoded values. The free SDK sends these defaults — no visual change. Premium sends configurable values.
|
|
936
|
+
|
|
937
|
+
### PR 2: Plugin Registration Hook (Optional)
|
|
938
|
+
|
|
939
|
+
```javascript
|
|
940
|
+
// In VIB3Engine:
|
|
941
|
+
registerPlugin(plugin) {
|
|
942
|
+
plugin.attach(this);
|
|
943
|
+
this._plugins.push(plugin);
|
|
944
|
+
}
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
This allows premium to attach cleanly without monkey-patching `setParameter()` and `updateCurrentSystemParameters()`.
|
|
948
|
+
|
|
949
|
+
### PR 3: Parameter Change Event Enhancement
|
|
950
|
+
|
|
951
|
+
Enhance `onParameterChange()` to include the parameter name that changed (not just the full state):
|
|
952
|
+
```javascript
|
|
953
|
+
// Current: listener(params)
|
|
954
|
+
// Enhanced: listener(params, { changed: ['hue', 'chaos'] })
|
|
955
|
+
```
|
|
956
|
+
|
|
957
|
+
This allows premium modules and framework sync to efficiently detect what changed without full-state diffing.
|
|
958
|
+
|
|
959
|
+
---
|
|
960
|
+
|
|
961
|
+
## Implementation Order
|
|
962
|
+
|
|
963
|
+
1. **Free SDK bug fixes** (PR to main) — u_dimension, dead audio, hue encoding
|
|
964
|
+
2. **Free SDK uniform declarations** (PR) — add new uniforms with defaults
|
|
965
|
+
3. **Create premium repo** — scaffold, CLAUDE.md, package.json
|
|
966
|
+
4. **ShaderParameterSurface** — most independent module, validates the architecture
|
|
967
|
+
5. **RotationLockSystem** — simple, high impact
|
|
968
|
+
6. **CSSBridge** — high demo value
|
|
969
|
+
7. **VisualEventSystem** — depends on having a working engine to test triggers
|
|
970
|
+
8. **LayerGeometryMixer** — may need upstream verification
|
|
971
|
+
9. **ChoreographyExtensions** — integrates multiple modules
|
|
972
|
+
10. **FrameworkSync** — lowest priority, clean enhancement
|
|
973
|
+
11. **PremiumMCPServer** — wraps everything, last to build
|
|
974
|
+
12. **Gold standard demos** — card-lift-portal.html, audio-storm.html, css-synchronized.html
|
|
975
|
+
|
|
976
|
+
---
|
|
977
|
+
|
|
978
|
+
*VIB3+ SDK — Clear Seas Solutions LLC*
|
|
979
|
+
*Expansion Design v1.0 — Feb 16, 2026*
|