@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
@@ -7,30 +7,30 @@
7
7
  * UnifiedRenderBridge instances — one per canvas — and coordinates shader
8
8
  * compilation, uniform updates, and rendering across all layers.
9
9
  *
10
+ * Layer parameters are derived through a LayerRelationshipGraph, where one
11
+ * layer acts as the keystone (driver) and others derive their state through
12
+ * configurable relationship functions — not static multipliers.
13
+ *
10
14
  * Usage:
11
15
  * const multi = new MultiCanvasBridge();
12
16
  * await multi.initialize({
13
- * canvases: {
14
- * background: document.getElementById('bg-canvas'),
15
- * shadow: document.getElementById('shadow-canvas'),
16
- * content: document.getElementById('content-canvas'),
17
- * highlight: document.getElementById('highlight-canvas'),
18
- * accent: document.getElementById('accent-canvas'),
19
- * },
20
- * preferWebGPU: true
17
+ * canvases: { background, shadow, content, highlight, accent },
18
+ * preferWebGPU: true,
19
+ * relationshipProfile: 'holographic' // or 'symmetry', 'chord', 'storm'
21
20
  * });
22
21
  *
23
22
  * multi.compileShaderAll('holographic', shaderSources);
24
- * multi.setSharedUniforms({ u_time: t, u_resolution: [w, h] });
25
- * multi.setLayerUniforms('background', { u_layerOpacity: 0.2, u_densityMult: 0.4 });
23
+ * multi.setKeystoneUniforms({ u_time: t, u_density: 1.0, u_hue: 320 });
26
24
  * multi.renderAll('holographic');
27
25
  */
28
26
 
29
27
  import { UnifiedRenderBridge } from './UnifiedRenderBridge.js';
28
+ import { LayerRelationshipGraph, LAYER_ORDER as GRAPH_LAYER_ORDER } from './LayerRelationshipGraph.js';
30
29
 
31
30
  /**
32
- * Default layer configuration matching the VIB3+ holographic system.
33
- * Each layer has role-specific opacity, density, and speed multipliers.
31
+ * Default layer configuration used as fallback when no relationship graph
32
+ * is active (legacy mode). Preserved for backward compatibility only.
33
+ * @deprecated Use LayerRelationshipGraph profiles instead.
34
34
  */
35
35
  const DEFAULT_LAYER_CONFIG = {
36
36
  background: { layerScale: 1.0, layerOpacity: 0.2, densityMult: 0.4, speedMult: 0.2 },
@@ -43,7 +43,7 @@ const DEFAULT_LAYER_CONFIG = {
43
43
  /**
44
44
  * Standard layer order (back to front).
45
45
  */
46
- const LAYER_ORDER = ['background', 'shadow', 'content', 'highlight', 'accent'];
46
+ const LAYER_ORDER = GRAPH_LAYER_ORDER;
47
47
 
48
48
  export class MultiCanvasBridge {
49
49
  constructor() {
@@ -59,7 +59,7 @@ export class MultiCanvasBridge {
59
59
  /** @type {Map<string, object>} Per-layer uniform overrides */
60
60
  this._layerUniforms = new Map();
61
61
 
62
- /** @type {Map<string, object>} Per-layer config (opacity, density, speed) */
62
+ /** @type {Map<string, object>} Per-layer config (opacity, density, speed) — legacy fallback */
63
63
  this._layerConfig = new Map();
64
64
 
65
65
  /** @type {boolean} */
@@ -67,6 +67,12 @@ export class MultiCanvasBridge {
67
67
 
68
68
  /** @type {string|null} Active backend type (set after init) */
69
69
  this._backendType = null;
70
+
71
+ /** @type {LayerRelationshipGraph|null} */
72
+ this._relationshipGraph = null;
73
+
74
+ /** @type {number} Frame time counter for relationship resolution */
75
+ this._frameTime = 0;
70
76
  }
71
77
 
72
78
  /**
@@ -76,7 +82,9 @@ export class MultiCanvasBridge {
76
82
  * @param {object} options.canvases - Map of layer name → HTMLCanvasElement
77
83
  * @param {boolean} [options.preferWebGPU=true] - Try WebGPU for each canvas
78
84
  * @param {boolean} [options.debug=false]
79
- * @param {object} [options.layerConfig] - Override default layer configuration
85
+ * @param {object} [options.layerConfig] - Override default layer configuration (legacy)
86
+ * @param {string} [options.relationshipProfile] - Named relationship profile to load
87
+ * @param {LayerRelationshipGraph} [options.relationshipGraph] - Pre-configured graph instance
80
88
  * @returns {Promise<void>}
81
89
  */
82
90
  async initialize(options) {
@@ -84,7 +92,9 @@ export class MultiCanvasBridge {
84
92
  canvases,
85
93
  preferWebGPU = true,
86
94
  debug = false,
87
- layerConfig = {}
95
+ layerConfig = {},
96
+ relationshipProfile,
97
+ relationshipGraph
88
98
  } = options;
89
99
 
90
100
  // Initialize bridges in parallel
@@ -102,7 +112,7 @@ export class MultiCanvasBridge {
102
112
  this._bridges.set(layerName, bridge);
103
113
  this._canvases.set(layerName, canvas);
104
114
 
105
- // Apply layer config (user override > default)
115
+ // Apply legacy layer config (user override > default)
106
116
  const config = {
107
117
  ...(DEFAULT_LAYER_CONFIG[layerName] || {}),
108
118
  ...(layerConfig[layerName] || {})
@@ -118,9 +128,19 @@ export class MultiCanvasBridge {
118
128
  }
119
129
  }
120
130
 
131
+ // Set up relationship graph
132
+ if (relationshipGraph instanceof LayerRelationshipGraph) {
133
+ this._relationshipGraph = relationshipGraph;
134
+ } else if (relationshipProfile) {
135
+ this._relationshipGraph = new LayerRelationshipGraph({ profile: relationshipProfile });
136
+ }
137
+
121
138
  this._initialized = this._bridges.size > 0;
122
139
  if (debug) {
123
- console.log(`MultiCanvasBridge: ${this._bridges.size}/${entries.length} layers initialized (${this._backendType})`);
140
+ const graphInfo = this._relationshipGraph
141
+ ? ` [graph: ${this._relationshipGraph.activeProfile || 'custom'}]`
142
+ : ' [legacy mode]';
143
+ console.log(`MultiCanvasBridge: ${this._bridges.size}/${entries.length} layers initialized (${this._backendType})${graphInfo}`);
124
144
  }
125
145
  }
126
146
 
@@ -157,6 +177,55 @@ export class MultiCanvasBridge {
157
177
  return this._bridges.get(layerName);
158
178
  }
159
179
 
180
+ // ========================================================================
181
+ // Layer Relationship Graph
182
+ // ========================================================================
183
+
184
+ /**
185
+ * Get the active relationship graph. Creates one with 'holographic' profile
186
+ * if none exists.
187
+ * @returns {LayerRelationshipGraph}
188
+ */
189
+ get relationshipGraph() {
190
+ if (!this._relationshipGraph) {
191
+ this._relationshipGraph = new LayerRelationshipGraph({ profile: 'holographic' });
192
+ }
193
+ return this._relationshipGraph;
194
+ }
195
+
196
+ /**
197
+ * Set or replace the relationship graph.
198
+ * @param {LayerRelationshipGraph} graph
199
+ */
200
+ set relationshipGraph(graph) {
201
+ this._relationshipGraph = graph;
202
+ }
203
+
204
+ /**
205
+ * Load a named relationship profile.
206
+ * @param {string} profileName - holographic, symmetry, chord, storm, legacy
207
+ */
208
+ loadRelationshipProfile(profileName) {
209
+ this.relationshipGraph.loadProfile(profileName);
210
+ }
211
+
212
+ /**
213
+ * Set the keystone (driver) layer.
214
+ * @param {string} layerName
215
+ */
216
+ setKeystone(layerName) {
217
+ this.relationshipGraph.setKeystone(layerName);
218
+ }
219
+
220
+ /**
221
+ * Set the relationship for a dependent layer.
222
+ * @param {string} layerName
223
+ * @param {string|Function|Object} relationship - Preset name, function, or { preset, config }
224
+ */
225
+ setLayerRelationship(layerName, relationship) {
226
+ this.relationshipGraph.setRelationship(layerName, relationship);
227
+ }
228
+
160
229
  // ========================================================================
161
230
  // Shader Compilation
162
231
  // ========================================================================
@@ -204,6 +273,7 @@ export class MultiCanvasBridge {
204
273
 
205
274
  /**
206
275
  * Set uniforms shared across all layers (e.g. time, resolution, geometry).
276
+ * When a relationship graph is active, these are treated as keystone parameters.
207
277
  *
208
278
  * @param {object} uniforms
209
279
  */
@@ -212,7 +282,17 @@ export class MultiCanvasBridge {
212
282
  }
213
283
 
214
284
  /**
215
- * Set per-layer uniform overrides (e.g. layerOpacity, densityMult).
285
+ * Alias for setSharedUniforms when using relationship graph mode.
286
+ * Makes intent clearer — these are the keystone's parameters.
287
+ *
288
+ * @param {object} uniforms - Keystone parameters to derive other layers from
289
+ */
290
+ setKeystoneUniforms(uniforms) {
291
+ this._sharedUniforms = uniforms;
292
+ }
293
+
294
+ /**
295
+ * Set per-layer uniform overrides. Applied after relationship resolution.
216
296
  *
217
297
  * @param {string} layerName
218
298
  * @param {object} uniforms
@@ -223,7 +303,8 @@ export class MultiCanvasBridge {
223
303
  }
224
304
 
225
305
  /**
226
- * Update the layer configuration.
306
+ * Update the legacy layer configuration.
307
+ * @deprecated Use setLayerRelationship() instead.
227
308
  *
228
309
  * @param {string} layerName
229
310
  * @param {object} config - Partial config update
@@ -236,15 +317,38 @@ export class MultiCanvasBridge {
236
317
  /**
237
318
  * Build the merged uniform set for a specific layer.
238
319
  *
239
- * Priority: shared < layer config < layer overrides
320
+ * When a relationship graph is active:
321
+ * 1. Shared uniforms are treated as keystone parameters
322
+ * 2. The graph resolves derived parameters for the layer
323
+ * 3. Per-layer overrides are applied on top
324
+ *
325
+ * Legacy fallback (no graph):
326
+ * Priority: shared < layer config < layer overrides
240
327
  *
241
328
  * @param {string} layerName
242
329
  * @returns {object}
243
330
  */
244
331
  _buildLayerUniforms(layerName) {
245
- const config = this._layerConfig.get(layerName) || {};
246
332
  const overrides = this._layerUniforms.get(layerName) || {};
247
333
 
334
+ if (this._relationshipGraph) {
335
+ // Relationship graph mode: resolve layer params from keystone
336
+ const resolved = this._relationshipGraph.resolve(
337
+ this._sharedUniforms,
338
+ layerName,
339
+ this._frameTime
340
+ );
341
+
342
+ // Map relationship output to shader uniforms
343
+ return {
344
+ ...resolved,
345
+ u_layerOpacity: resolved.layerOpacity || resolved.u_layerOpacity || 1.0,
346
+ ...overrides
347
+ };
348
+ }
349
+
350
+ // Legacy mode: static multipliers
351
+ const config = this._layerConfig.get(layerName) || {};
248
352
  return {
249
353
  ...this._sharedUniforms,
250
354
  u_layerScale: config.layerScale || 1.0,
@@ -260,15 +364,31 @@ export class MultiCanvasBridge {
260
364
  // ========================================================================
261
365
 
262
366
  /**
263
- * Render all layers in order using the named shader.
367
+ * Render all layers in order.
368
+ *
369
+ * When a relationship graph is active, each layer may use a different shader
370
+ * as assigned by graph.setLayerShader(). The shaderName parameter serves as
371
+ * the default for layers without an explicit shader assignment.
264
372
  *
265
- * @param {string} shaderName - Shader program to use
373
+ * @param {string} shaderName - Default shader program to use
266
374
  * @param {object} [options]
267
375
  * @param {number[]} [options.clearColor] - RGBA clear color
376
+ * @param {number} [options.time] - Frame time for relationship resolution
268
377
  */
269
378
  renderAll(shaderName, options = {}) {
379
+ if (options.time !== undefined) {
380
+ this._frameTime = options.time;
381
+ } else {
382
+ this._frameTime += 16; // ~60fps fallback
383
+ }
384
+
270
385
  for (const layerName of this.layerNames) {
271
- this.renderLayer(layerName, shaderName, options);
386
+ // Per-layer shader from relationship graph, or default
387
+ const layerShader = (this._relationshipGraph
388
+ ? this._relationshipGraph.getLayerShader(layerName)
389
+ : null) || shaderName;
390
+
391
+ this.renderLayer(layerName, layerShader, options);
272
392
  }
273
393
  }
274
394
 
@@ -334,7 +454,10 @@ export class MultiCanvasBridge {
334
454
  this._sharedUniforms = {};
335
455
  this._initialized = false;
336
456
  this._backendType = null;
457
+ this._relationshipGraph = null;
458
+ this._frameTime = 0;
337
459
  }
338
460
  }
339
461
 
462
+ export { DEFAULT_LAYER_CONFIG, LAYER_ORDER };
340
463
  export default MultiCanvasBridge;
@@ -199,6 +199,44 @@ export class ShaderLoader {
199
199
  return results;
200
200
  }
201
201
 
202
+ /**
203
+ * Resolve #include directives in shader source.
204
+ * GLSL: #include "common/rotation4d.glsl"
205
+ * WGSL: // @include "common/rotation4d.wgsl"
206
+ *
207
+ * Includes are resolved from the loader's cache (call loadCommonLibrary() first).
208
+ * Non-recursive — only resolves one level of includes.
209
+ *
210
+ * @param {string} source - Shader source with include directives
211
+ * @returns {string} Resolved shader source
212
+ */
213
+ resolveIncludes(source) {
214
+ if (!source) return source;
215
+
216
+ // GLSL: #include "path"
217
+ // WGSL: // @include "path"
218
+ const includeRegex = /(?:^|\n)\s*(?:#include|\/\/\s*@include)\s+"([^"]+)"\s*(?:\n|$)/g;
219
+
220
+ return source.replace(includeRegex, (match, path) => {
221
+ const cached = this._cache.get(path);
222
+ if (cached) {
223
+ return '\n// --- included from ' + path + ' ---\n' + cached + '\n// --- end ' + path + ' ---\n';
224
+ }
225
+ console.warn(`ShaderLoader: Include not found in cache: "${path}" — load it first via loadCommonLibrary()`);
226
+ return match; // Leave directive in place if not found
227
+ });
228
+ }
229
+
230
+ /**
231
+ * Load a shader file and resolve includes.
232
+ * @param {string} relativePath
233
+ * @returns {Promise<string|null>}
234
+ */
235
+ async loadAndResolve(relativePath) {
236
+ const source = await this.load(relativePath);
237
+ return source ? this.resolveIncludes(source) : null;
238
+ }
239
+
202
240
  /**
203
241
  * Clear all cached shaders.
204
242
  */
@@ -384,10 +384,10 @@ export const ShaderLib = {
384
384
  mat4 rotateXZ(float angle) {
385
385
  float c = cos(angle), s = sin(angle);
386
386
  return mat4(
387
- c, 0, -s, 0,
388
- 0, 1, 0, 0,
389
- s, 0, c, 0,
390
- 0, 0, 0, 1
387
+ c, 0, s, 0,
388
+ 0, 1, 0, 0,
389
+ -s, 0, c, 0,
390
+ 0, 0, 0, 1
391
391
  );
392
392
  }
393
393
 
@@ -25,7 +25,7 @@ import { createWebGPUBackend, isWebGPUSupported, WGSLShaderLib } from './backend
25
25
  * @returns {Float32Array}
26
26
  */
27
27
  function packVIB3Uniforms(uniforms) {
28
- // Total: 32 floats = 128 bytes → aligned to 256 bytes in buffer
28
+ // Total: 33 floats (indices 0-32) = 132 bytes → padded to 256 bytes in buffer
29
29
  const data = new Float32Array(64); // 256 bytes
30
30
 
31
31
  data[0] = uniforms.u_time || 0;
@@ -56,6 +56,9 @@ function packVIB3Uniforms(uniforms) {
56
56
  data[22] = uniforms.u_mid || 0;
57
57
  data[23] = uniforms.u_high || 0;
58
58
 
59
+ // Breath/Vitality parameter
60
+ data[32] = uniforms.u_breath || 0;
61
+
59
62
  data[24] = uniforms.u_layerScale || 1.0;
60
63
  data[25] = uniforms.u_layerOpacity || 1.0;
61
64
  data[26] = 0; // _pad1
@@ -152,10 +152,14 @@ struct VIB3Uniforms {
152
152
  layerScale: f32,
153
153
  layerOpacity: f32,
154
154
  _pad1: f32,
155
- layerColor: vec3<f32>,
155
+ layerColorR: f32,
156
+ layerColorG: f32,
157
+ layerColorB: f32,
156
158
  densityMult: f32,
157
159
  speedMult: f32,
158
- _pad2: vec3<f32>,
160
+
161
+ // Vitality
162
+ breath: f32,
159
163
  };
160
164
  `;
161
165
 
@@ -178,9 +182,9 @@ fn rotateXZ(angle: f32) -> mat4x4<f32> {
178
182
  let c = cos(angle);
179
183
  let s = sin(angle);
180
184
  return mat4x4<f32>(
181
- vec4<f32>(c, 0.0, -s, 0.0),
185
+ vec4<f32>( c, 0.0, s, 0.0),
182
186
  vec4<f32>(0.0, 1.0, 0.0, 0.0),
183
- vec4<f32>(s, 0.0, c, 0.0),
187
+ vec4<f32>(-s, 0.0, c, 0.0),
184
188
  vec4<f32>(0.0, 0.0, 0.0, 1.0)
185
189
  );
186
190
  }
@@ -119,6 +119,31 @@ export {
119
119
  MultiCanvasBridge
120
120
  } from './MultiCanvasBridge.js';
121
121
 
122
+ // Layer relationship graph (keystone-driven inter-layer parameter system)
123
+ export {
124
+ LayerRelationshipGraph,
125
+ LAYER_ORDER,
126
+ PROFILES,
127
+ PRESET_REGISTRY,
128
+ echo,
129
+ mirror,
130
+ complement,
131
+ harmonic,
132
+ reactive,
133
+ chase
134
+ } from './LayerRelationshipGraph.js';
135
+
136
+ // Layer preset manager (save/load/tune relationship presets)
137
+ export {
138
+ LayerPresetManager
139
+ } from './LayerPresetManager.js';
140
+
141
+ // Layer reactivity bridge (audio/tilt/input → relationship modulation)
142
+ export {
143
+ LayerReactivityBridge,
144
+ MODULATION_PROFILES
145
+ } from './LayerReactivityBridge.js';
146
+
122
147
  /**
123
148
  * Create a complete rendering context
124
149
  * @param {HTMLCanvasElement} canvas
@@ -129,8 +154,7 @@ export function createRenderContext(canvas, options = {}) {
129
154
  if (options.backend === 'webgpu') {
130
155
  return null;
131
156
  }
132
- const { createWebGLBackend } = require('./backends/WebGLBackend.js');
133
- const backend = createWebGLBackend(canvas, options);
157
+ const backend = _createWebGLBackend(canvas, options);
134
158
 
135
159
  if (!backend) {
136
160
  return null;
@@ -365,3 +389,4 @@ import { RenderState } from './RenderState.js';
365
389
  import { ShaderProgram, ShaderLib } from './ShaderProgram.js';
366
390
  import { UnifiedRenderBridge } from './UnifiedRenderBridge.js';
367
391
  import { createWebGPUBackend } from './backends/WebGPUBackend.js';
392
+ import { createWebGLBackend as _createWebGLBackend } from './backends/WebGLBackend.js';
@@ -500,29 +500,74 @@ export class Node4D {
500
500
  * @private
501
501
  */
502
502
  _updateLocalMatrix() {
503
- // Start with identity
504
- this._localMatrix = Mat4x4.identity();
503
+ // Ensure matrix exists
504
+ if (!this._localMatrix) {
505
+ this._localMatrix = new Mat4x4();
506
+ }
507
+
508
+ const m = this._localMatrix.data;
509
+ const s = this._scale;
510
+ const p = this._position;
511
+
512
+ // 1. Write rotation directly to local matrix (No allocation)
513
+ this._rotation.toMatrix(m);
514
+
515
+ // 2. Apply scale (Diagonal matrix multiplication on the right)
516
+ // M = M * S
517
+ // Columns of M are scaled by s.x, s.y, s.z, s.w
518
+
519
+ // Col 0
520
+ m[0] *= s.x; m[1] *= s.x; m[2] *= s.x; m[3] *= s.x;
521
+ // Col 1
522
+ m[4] *= s.y; m[5] *= s.y; m[6] *= s.y; m[7] *= s.y;
523
+ // Col 2
524
+ m[8] *= s.z; m[9] *= s.z; m[10] *= s.z; m[11] *= s.z;
525
+ // Col 3
526
+ m[12] *= s.w; m[13] *= s.w; m[14] *= s.w; m[15] *= s.w;
527
+
528
+ // 3. Apply translation (Matrix multiplication on the left)
529
+ // M = T * M
530
+ // T is standard 3D translation:
531
+ // [ 1 0 0 px ]
532
+ // [ 0 1 0 py ]
533
+ // [ 0 0 1 pz ]
534
+ // [ 0 0 0 1 ]
535
+ //
536
+ // Row 0 += px * Row 3
537
+ // Row 1 += py * Row 3
538
+ // Row 2 += pz * Row 3
539
+
540
+ const px = p.x;
541
+ const py = p.y;
542
+ const pz = p.z;
543
+
544
+ // Row 3 elements of M (which are used in the calculation)
545
+ const m3 = m[3];
546
+ const m7 = m[7];
547
+ const m11 = m[11];
548
+ const m15 = m[15];
549
+
550
+ if (px !== 0) {
551
+ m[0] += px * m3;
552
+ m[4] += px * m7;
553
+ m[8] += px * m11;
554
+ m[12] += px * m15;
555
+ }
556
+
557
+ if (py !== 0) {
558
+ m[1] += py * m3;
559
+ m[5] += py * m7;
560
+ m[9] += py * m11;
561
+ m[13] += py * m15;
562
+ }
563
+
564
+ if (pz !== 0) {
565
+ m[2] += pz * m3;
566
+ m[6] += pz * m7;
567
+ m[10] += pz * m11;
568
+ m[14] += pz * m15;
569
+ }
505
570
 
506
- // Apply scale
507
- const scaleMatrix = Mat4x4.identity();
508
- scaleMatrix.set(0, 0, this._scale.x);
509
- scaleMatrix.set(1, 1, this._scale.y);
510
- scaleMatrix.set(2, 2, this._scale.z);
511
- scaleMatrix.set(3, 3, this._scale.w);
512
-
513
- // Apply rotation (toMatrix returns Float32Array, wrap in Mat4x4)
514
- const rotationMatrix = new Mat4x4(this._rotation.toMatrix());
515
-
516
- // Apply translation (in 4D, translation is stored in last column, keep [3,3]=1)
517
- const translationMatrix = Mat4x4.identity();
518
- translationMatrix.set(0, 3, this._position.x);
519
- translationMatrix.set(1, 3, this._position.y);
520
- translationMatrix.set(2, 3, this._position.z);
521
- // Note: position.w is the 4th spatial coordinate, handled separately
522
- // Matrix[3,3] must remain 1 for proper transformation
523
-
524
- // Compose: T * R * S
525
- this._localMatrix = translationMatrix.multiply(rotationMatrix).multiply(scaleMatrix);
526
571
  this._localDirty = false;
527
572
  }
528
573
 
@@ -535,10 +580,15 @@ export class Node4D {
535
580
  this._updateLocalMatrix();
536
581
  }
537
582
 
583
+ // Ensure matrix exists
584
+ if (!this._worldMatrix) {
585
+ this._worldMatrix = new Mat4x4();
586
+ }
587
+
538
588
  if (this._parent) {
539
- this._worldMatrix = this._parent.worldMatrix.multiply(this._localMatrix);
589
+ this._parent.worldMatrix.multiply(this._localMatrix, this._worldMatrix);
540
590
  } else {
541
- this._worldMatrix = this._localMatrix.clone();
591
+ this._worldMatrix.copy(this._localMatrix);
542
592
  }
543
593
 
544
594
  this._worldDirty = false;
@@ -60,10 +60,10 @@ export function createSceneContext(options = {}) {
60
60
  poolInitialSize = 100
61
61
  } = options;
62
62
 
63
- const scene = new (require('./Scene4D.js').Scene4D)(sceneName);
64
- const resources = new (require('./ResourceManager.js').ResourceManager)();
65
- const disposal = new (require('./Disposable.js').DisposalManager)();
66
- const poolManager = new (require('./MemoryPool.js').PoolManager)();
63
+ const scene = new Scene4D(sceneName);
64
+ const resources = new ResourceManager();
65
+ const disposal = new DisposalManager();
66
+ const poolManager = new PoolManager();
67
67
 
68
68
  resources.memoryLimit = memoryLimit;
69
69
 
@@ -53,6 +53,71 @@ float hypertetrahedronCore(vec4 p, float baseType) {
53
53
  return max(baseShape, tetraField);
54
54
  }
55
55
 
56
+ // ── Polytope Core Warp Functions ──
57
+ // Requires: rotation matrices from rotation4d.glsl, project4Dto3D, and u_* uniforms
58
+
59
+ vec3 warpHypersphereCore(vec3 p, int geometryIndex, vec2 mouseDelta) {
60
+ float radius = length(p);
61
+ float morphBlend = clamp(u_morphFactor * 0.6 + (u_dimension - 3.0) * 0.25, 0.0, 2.0);
62
+ float w = sin(radius * (1.3 + float(geometryIndex) * 0.12) + u_time * 0.0008 * u_speed);
63
+ w *= (0.4 + morphBlend * 0.45);
64
+
65
+ vec4 p4d = vec4(p * (1.0 + morphBlend * 0.2), w);
66
+ p4d = rotateXY(u_rot4dXY) * p4d;
67
+ p4d = rotateXZ(u_rot4dXZ) * p4d;
68
+ p4d = rotateYZ(u_rot4dYZ) * p4d;
69
+ p4d = rotateXW(u_rot4dXW) * p4d;
70
+ p4d = rotateYW(u_rot4dYW) * p4d;
71
+ p4d = rotateZW(u_rot4dZW) * p4d;
72
+
73
+ vec3 projected = project4Dto3D(p4d);
74
+ return mix(p, projected, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
75
+ }
76
+
77
+ vec3 warpHypertetraCore(vec3 p, int geometryIndex, vec2 mouseDelta) {
78
+ vec3 c1 = normalize(vec3(1.0, 1.0, 1.0));
79
+ vec3 c2 = normalize(vec3(-1.0, -1.0, 1.0));
80
+ vec3 c3 = normalize(vec3(-1.0, 1.0, -1.0));
81
+ vec3 c4 = normalize(vec3(1.0, -1.0, -1.0));
82
+
83
+ float morphBlend = clamp(u_morphFactor * 0.8 + (u_dimension - 3.0) * 0.2, 0.0, 2.0);
84
+ float basisMix = dot(p, c1) * 0.14 + dot(p, c2) * 0.1 + dot(p, c3) * 0.08;
85
+ float w = sin(basisMix * 5.5 + u_time * 0.0009 * u_speed);
86
+ w *= cos(dot(p, c4) * 4.2 - u_time * 0.0007 * u_speed);
87
+ w *= (0.5 + morphBlend * 0.4);
88
+
89
+ vec3 offset = vec3(dot(p, c1), dot(p, c2), dot(p, c3)) * 0.1 * morphBlend;
90
+ vec4 p4d = vec4(p + offset, w);
91
+ p4d = rotateXY(u_rot4dXY) * p4d;
92
+ p4d = rotateXZ(u_rot4dXZ) * p4d;
93
+ p4d = rotateYZ(u_rot4dYZ) * p4d;
94
+ p4d = rotateXW(u_rot4dXW) * p4d;
95
+ p4d = rotateYW(u_rot4dYW) * p4d;
96
+ p4d = rotateZW(u_rot4dZW) * p4d;
97
+
98
+ vec3 projected = project4Dto3D(p4d);
99
+ float planeInfluence = min(min(abs(dot(p, c1)), abs(dot(p, c2))),
100
+ min(abs(dot(p, c3)), abs(dot(p, c4))));
101
+ vec3 blended = mix(p, projected, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
102
+ return mix(blended, blended * (1.0 - planeInfluence * 0.55), 0.2 + morphBlend * 0.2);
103
+ }
104
+
105
+ vec3 applyCoreWarp(vec3 p, float geometryType, vec2 mouseDelta) {
106
+ float totalBase = 8.0;
107
+ float coreFloat = floor(geometryType / totalBase);
108
+ int coreIndex = int(clamp(coreFloat, 0.0, 2.0));
109
+ float baseGeomFloat = geometryType - floor(geometryType / totalBase) * totalBase;
110
+ int geometryIndex = int(clamp(floor(baseGeomFloat + 0.5), 0.0, totalBase - 1.0));
111
+
112
+ if (coreIndex == 1) {
113
+ return warpHypersphereCore(p, geometryIndex, mouseDelta);
114
+ }
115
+ if (coreIndex == 2) {
116
+ return warpHypertetraCore(p, geometryIndex, mouseDelta);
117
+ }
118
+ return p;
119
+ }
120
+
56
121
  // Main geometry dispatcher (0-23)
57
122
  float geometry(vec4 p, float type) {
58
123
  if (type < 8.0) {