@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
|
@@ -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
|
-
*
|
|
15
|
-
*
|
|
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.
|
|
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
|
|
33
|
-
*
|
|
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 =
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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 -
|
|
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
|
-
|
|
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,
|
|
388
|
-
0, 1,
|
|
389
|
-
|
|
390
|
-
0, 0,
|
|
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:
|
|
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
|
-
|
|
155
|
+
layerColorR: f32,
|
|
156
|
+
layerColorG: f32,
|
|
157
|
+
layerColorB: f32,
|
|
156
158
|
densityMult: f32,
|
|
157
159
|
speedMult: f32,
|
|
158
|
-
|
|
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,
|
|
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
|
}
|
package/src/render/index.js
CHANGED
|
@@ -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
|
|
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';
|
package/src/scene/Node4D.js
CHANGED
|
@@ -500,29 +500,74 @@ export class Node4D {
|
|
|
500
500
|
* @private
|
|
501
501
|
*/
|
|
502
502
|
_updateLocalMatrix() {
|
|
503
|
-
//
|
|
504
|
-
this._localMatrix
|
|
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.
|
|
589
|
+
this._parent.worldMatrix.multiply(this._localMatrix, this._worldMatrix);
|
|
540
590
|
} else {
|
|
541
|
-
this._worldMatrix
|
|
591
|
+
this._worldMatrix.copy(this._localMatrix);
|
|
542
592
|
}
|
|
543
593
|
|
|
544
594
|
this._worldDirty = false;
|
package/src/scene/index.js
CHANGED
|
@@ -60,10 +60,10 @@ export function createSceneContext(options = {}) {
|
|
|
60
60
|
poolInitialSize = 100
|
|
61
61
|
} = options;
|
|
62
62
|
|
|
63
|
-
const scene = new
|
|
64
|
-
const resources = new
|
|
65
|
-
const disposal = new
|
|
66
|
-
const poolManager = new
|
|
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) {
|