@vib3code/sdk 2.0.1
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 +118 -0
- package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
- package/DOCS/CI_TESTING.md +38 -0
- package/DOCS/CLI_ONBOARDING.md +75 -0
- package/DOCS/CONTROL_REFERENCE.md +64 -0
- package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
- package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
- package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
- package/DOCS/ENV_SETUP.md +189 -0
- package/DOCS/EXPORT_FORMATS.md +417 -0
- package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
- package/DOCS/LICENSING_TIERS.md +275 -0
- package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
- package/DOCS/OBS_SETUP_GUIDE.md +98 -0
- package/DOCS/PROJECT_SETUP.md +66 -0
- package/DOCS/RENDERER_LIFECYCLE.md +40 -0
- package/DOCS/REPO_MANIFEST.md +121 -0
- package/DOCS/SESSION_014_PLAN.md +195 -0
- package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
- package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
- package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
- package/DOCS/SYSTEM_INVENTORY.md +520 -0
- package/DOCS/TELEMETRY_EXPORTS.md +34 -0
- package/DOCS/WEBGPU_STATUS.md +38 -0
- package/DOCS/XR_BENCHMARKS.md +608 -0
- package/LICENSE +21 -0
- package/README.md +426 -0
- package/docs/.nojekyll +0 -0
- package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/02-hyperspatial_ego_death.html +346 -0
- package/docs/03-post_cartesian_sublime.html +346 -0
- package/docs/04-crystalline_void_meditation.html +346 -0
- package/docs/05-quantum_decoherence_ballet.html +346 -0
- package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/07-hyperspatial_ego_death.html +346 -0
- package/docs/08-post_cartesian_sublime.html +346 -0
- package/docs/09-crystalline_void_meditation.html +346 -0
- package/docs/10-quantum_decoherence_ballet.html +346 -0
- package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/12-hyperspatial_ego_death.html +346 -0
- package/docs/13-post_cartesian_sublime.html +346 -0
- package/docs/index.html +794 -0
- package/docs/test-hub.html +441 -0
- package/docs/url-state.js +102 -0
- package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
- package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
- package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
- package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
- package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
- package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
- package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
- package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
- package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
- package/docs/vib3-exports/index.html +238 -0
- package/docs/webgpu-live.html +702 -0
- package/package.json +367 -0
- package/src/advanced/AIPresetGenerator.js +777 -0
- package/src/advanced/MIDIController.js +703 -0
- package/src/advanced/OffscreenWorker.js +1051 -0
- package/src/advanced/WebGPUCompute.js +1051 -0
- package/src/advanced/WebXRRenderer.js +680 -0
- package/src/agent/cli/AgentCLI.js +615 -0
- package/src/agent/cli/index.js +14 -0
- package/src/agent/index.js +73 -0
- package/src/agent/mcp/MCPServer.js +950 -0
- package/src/agent/mcp/index.js +9 -0
- package/src/agent/mcp/tools.js +548 -0
- package/src/agent/telemetry/EventStream.js +669 -0
- package/src/agent/telemetry/Instrumentation.js +618 -0
- package/src/agent/telemetry/TelemetryExporters.js +427 -0
- package/src/agent/telemetry/TelemetryService.js +464 -0
- package/src/agent/telemetry/index.js +52 -0
- package/src/benchmarks/BenchmarkRunner.js +381 -0
- package/src/benchmarks/MetricsCollector.js +299 -0
- package/src/benchmarks/index.js +9 -0
- package/src/benchmarks/scenes.js +259 -0
- package/src/cli/index.js +675 -0
- package/src/config/ApiConfig.js +88 -0
- package/src/core/CanvasManager.js +217 -0
- package/src/core/ErrorReporter.js +117 -0
- package/src/core/ParameterMapper.js +333 -0
- package/src/core/Parameters.js +396 -0
- package/src/core/RendererContracts.js +200 -0
- package/src/core/UnifiedResourceManager.js +370 -0
- package/src/core/VIB3Engine.js +636 -0
- package/src/core/renderers/FacetedRendererAdapter.js +32 -0
- package/src/core/renderers/HolographicRendererAdapter.js +29 -0
- package/src/core/renderers/QuantumRendererAdapter.js +29 -0
- package/src/core/renderers/RendererLifecycleManager.js +63 -0
- package/src/creative/ColorPresetsSystem.js +980 -0
- package/src/creative/ParameterTimeline.js +1061 -0
- package/src/creative/PostProcessingPipeline.js +1113 -0
- package/src/creative/TransitionAnimator.js +683 -0
- package/src/export/CSSExporter.js +226 -0
- package/src/export/CardGeneratorBase.js +279 -0
- package/src/export/ExportManager.js +580 -0
- package/src/export/FacetedCardGenerator.js +279 -0
- package/src/export/HolographicCardGenerator.js +543 -0
- package/src/export/LottieExporter.js +552 -0
- package/src/export/QuantumCardGenerator.js +315 -0
- package/src/export/SVGExporter.js +519 -0
- package/src/export/ShaderExporter.js +903 -0
- package/src/export/TradingCardGenerator.js +3055 -0
- package/src/export/TradingCardManager.js +181 -0
- package/src/export/VIB3PackageExporter.js +559 -0
- package/src/export/index.js +14 -0
- package/src/export/systems/TradingCardSystemFaceted.js +494 -0
- package/src/export/systems/TradingCardSystemHolographic.js +452 -0
- package/src/export/systems/TradingCardSystemQuantum.js +411 -0
- package/src/faceted/FacetedSystem.js +963 -0
- package/src/features/CollectionManager.js +433 -0
- package/src/gallery/CollectionManager.js +240 -0
- package/src/gallery/GallerySystem.js +485 -0
- package/src/geometry/GeometryFactory.js +314 -0
- package/src/geometry/GeometryLibrary.js +72 -0
- package/src/geometry/buffers/BufferBuilder.js +338 -0
- package/src/geometry/buffers/index.js +18 -0
- package/src/geometry/generators/Crystal.js +420 -0
- package/src/geometry/generators/Fractal.js +298 -0
- package/src/geometry/generators/KleinBottle.js +197 -0
- package/src/geometry/generators/Sphere.js +192 -0
- package/src/geometry/generators/Tesseract.js +160 -0
- package/src/geometry/generators/Tetrahedron.js +225 -0
- package/src/geometry/generators/Torus.js +304 -0
- package/src/geometry/generators/Wave.js +341 -0
- package/src/geometry/index.js +142 -0
- package/src/geometry/warp/HypersphereCore.js +211 -0
- package/src/geometry/warp/HypertetraCore.js +386 -0
- package/src/geometry/warp/index.js +57 -0
- package/src/holograms/HolographicVisualizer.js +1073 -0
- package/src/holograms/RealHolographicSystem.js +966 -0
- package/src/holograms/variantRegistry.js +69 -0
- package/src/integrations/FigmaPlugin.js +854 -0
- package/src/integrations/OBSMode.js +754 -0
- package/src/integrations/ThreeJsPackage.js +660 -0
- package/src/integrations/TouchDesignerExport.js +552 -0
- package/src/integrations/frameworks/Vib3React.js +591 -0
- package/src/integrations/frameworks/Vib3Svelte.js +654 -0
- package/src/integrations/frameworks/Vib3Vue.js +628 -0
- package/src/llm/LLMParameterInterface.js +240 -0
- package/src/llm/LLMParameterUI.js +577 -0
- package/src/math/Mat4x4.js +708 -0
- package/src/math/Projection.js +341 -0
- package/src/math/Rotor4D.js +637 -0
- package/src/math/Vec4.js +476 -0
- package/src/math/constants.js +164 -0
- package/src/math/index.js +68 -0
- package/src/math/projections.js +54 -0
- package/src/math/rotations.js +196 -0
- package/src/quantum/QuantumEngine.js +906 -0
- package/src/quantum/QuantumVisualizer.js +1103 -0
- package/src/reactivity/ReactivityConfig.js +499 -0
- package/src/reactivity/ReactivityManager.js +586 -0
- package/src/reactivity/SpatialInputSystem.js +1783 -0
- package/src/reactivity/index.js +93 -0
- package/src/render/CommandBuffer.js +465 -0
- package/src/render/MultiCanvasBridge.js +340 -0
- package/src/render/RenderCommand.js +514 -0
- package/src/render/RenderResourceRegistry.js +523 -0
- package/src/render/RenderState.js +552 -0
- package/src/render/RenderTarget.js +512 -0
- package/src/render/ShaderLoader.js +253 -0
- package/src/render/ShaderProgram.js +599 -0
- package/src/render/UnifiedRenderBridge.js +496 -0
- package/src/render/backends/WebGLBackend.js +1108 -0
- package/src/render/backends/WebGPUBackend.js +1409 -0
- package/src/render/commands/CommandBufferExecutor.js +607 -0
- package/src/render/commands/RenderCommandBuffer.js +661 -0
- package/src/render/commands/index.js +17 -0
- package/src/render/index.js +367 -0
- package/src/scene/Disposable.js +498 -0
- package/src/scene/MemoryPool.js +618 -0
- package/src/scene/Node4D.js +697 -0
- package/src/scene/ResourceManager.js +599 -0
- package/src/scene/Scene4D.js +540 -0
- package/src/scene/index.js +98 -0
- package/src/schemas/error.schema.json +84 -0
- package/src/schemas/extension.schema.json +88 -0
- package/src/schemas/index.js +214 -0
- package/src/schemas/parameters.schema.json +142 -0
- package/src/schemas/tool-pack.schema.json +44 -0
- package/src/schemas/tool-response.schema.json +127 -0
- package/src/shaders/common/fullscreen.vert.glsl +5 -0
- package/src/shaders/common/fullscreen.vert.wgsl +17 -0
- package/src/shaders/common/geometry24.glsl +65 -0
- package/src/shaders/common/geometry24.wgsl +54 -0
- package/src/shaders/common/rotation4d.glsl +85 -0
- package/src/shaders/common/rotation4d.wgsl +86 -0
- package/src/shaders/common/uniforms.glsl +44 -0
- package/src/shaders/common/uniforms.wgsl +48 -0
- package/src/shaders/faceted/faceted.frag.glsl +129 -0
- package/src/shaders/faceted/faceted.frag.wgsl +164 -0
- package/src/shaders/holographic/holographic.frag.glsl +406 -0
- package/src/shaders/holographic/holographic.frag.wgsl +185 -0
- package/src/shaders/quantum/quantum.frag.glsl +513 -0
- package/src/shaders/quantum/quantum.frag.wgsl +361 -0
- package/src/testing/ParallelTestFramework.js +519 -0
- package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
- package/src/testing/exportFormats.test.js +8 -0
- package/src/testing/projections.test.js +14 -0
- package/src/testing/rotations.test.js +37 -0
- package/src/ui/InteractivityMenu.js +516 -0
- package/src/ui/StatusManager.js +96 -0
- package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
- package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
- package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
- package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
- package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
- package/src/variations/VariationManager.js +431 -0
- package/src/viewer/AudioReactivity.js +505 -0
- package/src/viewer/CardBending.js +481 -0
- package/src/viewer/GalleryUI.js +832 -0
- package/src/viewer/ReactivityManager.js +590 -0
- package/src/viewer/TradingCardExporter.js +600 -0
- package/src/viewer/ViewerPortal.js +374 -0
- package/src/viewer/index.js +12 -0
- package/src/wasm/WasmLoader.js +296 -0
- package/src/wasm/index.js +132 -0
- package/tools/agentic/mcpTools.js +88 -0
- package/tools/cli/agent-cli.js +92 -0
- package/tools/export/formats.js +24 -0
- package/tools/math/rotation-baseline.mjs +64 -0
- package/tools/shader-sync-verify.js +937 -0
- package/tools/telemetry/manifestPipeline.js +141 -0
- package/tools/telemetry/telemetryEvents.js +35 -0
- package/types/adaptive-sdk.d.ts +185 -0
- package/types/advanced/AIPresetGenerator.d.ts +81 -0
- package/types/advanced/MIDIController.d.ts +100 -0
- package/types/advanced/OffscreenWorker.d.ts +82 -0
- package/types/advanced/WebGPUCompute.d.ts +52 -0
- package/types/advanced/WebXRRenderer.d.ts +77 -0
- package/types/advanced/index.d.ts +46 -0
- package/types/core/ErrorReporter.d.ts +50 -0
- package/types/core/VIB3Engine.d.ts +204 -0
- package/types/creative/ColorPresetsSystem.d.ts +91 -0
- package/types/creative/ParameterTimeline.d.ts +74 -0
- package/types/creative/PostProcessingPipeline.d.ts +109 -0
- package/types/creative/TransitionAnimator.d.ts +71 -0
- package/types/creative/index.d.ts +35 -0
- package/types/integrations/FigmaPlugin.d.ts +46 -0
- package/types/integrations/OBSMode.d.ts +74 -0
- package/types/integrations/ThreeJsPackage.d.ts +62 -0
- package/types/integrations/TouchDesignerExport.d.ts +36 -0
- package/types/integrations/Vib3React.d.ts +74 -0
- package/types/integrations/Vib3Svelte.d.ts +63 -0
- package/types/integrations/Vib3Vue.d.ts +55 -0
- package/types/integrations/index.d.ts +52 -0
- package/types/reactivity/SpatialInputSystem.d.ts +173 -0
- package/types/reactivity/index.d.ts +394 -0
- package/types/render/CommandBuffer.d.ts +169 -0
- package/types/render/RenderCommand.d.ts +312 -0
- package/types/render/RenderState.d.ts +279 -0
- package/types/render/RenderTarget.d.ts +254 -0
- package/types/render/ShaderProgram.d.ts +277 -0
- package/types/render/UnifiedRenderBridge.d.ts +143 -0
- package/types/render/WebGLBackend.d.ts +168 -0
- package/types/render/WebGPUBackend.d.ts +186 -0
- package/types/render/index.d.ts +141 -0
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Quantum Hypertetra Fractal</title>
|
|
7
|
+
<style>
|
|
8
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
9
|
+
body { background: #000; overflow: hidden; font-family: 'Segoe UI', system-ui, sans-serif; }
|
|
10
|
+
canvas { display: block; width: 100vw; height: 100vh; }
|
|
11
|
+
.info {
|
|
12
|
+
position: fixed;
|
|
13
|
+
bottom: 20px;
|
|
14
|
+
left: 20px;
|
|
15
|
+
background: rgba(0,0,0,0.8);
|
|
16
|
+
border: 1px solid rgba(100,255,150,0.3);
|
|
17
|
+
border-radius: 8px;
|
|
18
|
+
padding: 15px 20px;
|
|
19
|
+
color: #fff;
|
|
20
|
+
font-size: 12px;
|
|
21
|
+
backdrop-filter: blur(10px);
|
|
22
|
+
max-width: 320px;
|
|
23
|
+
}
|
|
24
|
+
.info h3 { color: #64ff96; margin-bottom: 8px; font-size: 14px; }
|
|
25
|
+
.info p { opacity: 0.8; line-height: 1.4; margin-bottom: 8px; }
|
|
26
|
+
.info .meta { font-size: 10px; opacity: 0.6; border-top: 1px solid rgba(255,255,255,0.1); padding-top: 8px; }
|
|
27
|
+
.audio-btn {
|
|
28
|
+
position: fixed;
|
|
29
|
+
top: 20px;
|
|
30
|
+
right: 20px;
|
|
31
|
+
background: rgba(0,0,0,0.8);
|
|
32
|
+
border: 1px solid rgba(100,255,150,0.3);
|
|
33
|
+
border-radius: 8px;
|
|
34
|
+
padding: 10px 15px;
|
|
35
|
+
color: #64ff96;
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
font-size: 12px;
|
|
38
|
+
}
|
|
39
|
+
.audio-btn:hover { background: rgba(100,255,150,0.2); }
|
|
40
|
+
</style>
|
|
41
|
+
</head>
|
|
42
|
+
<body>
|
|
43
|
+
<canvas id="vib3"></canvas>
|
|
44
|
+
<div class="info">
|
|
45
|
+
<h3>Quantum Hypertetra Fractal</h3>
|
|
46
|
+
<p>Hypertetrahedron core with fractal base - 5-cell pentatope projection creates recursive self-similar structures</p>
|
|
47
|
+
<div class="meta">
|
|
48
|
+
System: QUANTUM<br>
|
|
49
|
+
Geometry: 21 (Hypertetra)<br>
|
|
50
|
+
VIB3+ Export • 1/26/2026
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
<button class="audio-btn" onclick="toggleAudio()">🎵 Enable Audio</button>
|
|
54
|
+
|
|
55
|
+
<script>
|
|
56
|
+
// VIB3+ Exported Visualization
|
|
57
|
+
// System: quantum
|
|
58
|
+
// Generated: 2026-01-26T22:37:57.874Z
|
|
59
|
+
|
|
60
|
+
const CONFIG = {
|
|
61
|
+
system: 'quantum',
|
|
62
|
+
geometry: 21,
|
|
63
|
+
params: {
|
|
64
|
+
"gridDensity": 25,
|
|
65
|
+
"morphFactor": 1.8,
|
|
66
|
+
"chaos": 0.35,
|
|
67
|
+
"speed": 0.5,
|
|
68
|
+
"hue": 60,
|
|
69
|
+
"intensity": 0.85,
|
|
70
|
+
"saturation": 0.75,
|
|
71
|
+
"dimension": 4,
|
|
72
|
+
"rot4dXY": 0,
|
|
73
|
+
"rot4dXZ": 0,
|
|
74
|
+
"rot4dYZ": 0,
|
|
75
|
+
"rot4dXW": 1.2,
|
|
76
|
+
"rot4dYW": 0.9,
|
|
77
|
+
"rot4dZW": 1.5
|
|
78
|
+
},
|
|
79
|
+
reactivity: {
|
|
80
|
+
"audio": {
|
|
81
|
+
"enabled": true,
|
|
82
|
+
"sensitivity": 1.8
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const canvas = document.getElementById('vib3');
|
|
88
|
+
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
|
|
89
|
+
|
|
90
|
+
if (!gl) {
|
|
91
|
+
document.body.innerHTML = '<div style="color:#64ff96;padding:40px;text-align:center;"><h2>WebGL Required</h2><p>Please enable WebGL to view this visualization.</p></div>';
|
|
92
|
+
throw new Error('WebGL not supported');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Compile shaders
|
|
96
|
+
function createShader(type, source) {
|
|
97
|
+
const shader = gl.createShader(type);
|
|
98
|
+
gl.shaderSource(shader, source);
|
|
99
|
+
gl.compileShader(shader);
|
|
100
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
101
|
+
console.error('Shader error:', gl.getShaderInfoLog(shader));
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return shader;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const vs = createShader(gl.VERTEX_SHADER, `
|
|
108
|
+
attribute vec2 a_position;
|
|
109
|
+
void main() {
|
|
110
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
111
|
+
}`);
|
|
112
|
+
const fs = createShader(gl.FRAGMENT_SHADER, `
|
|
113
|
+
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
114
|
+
precision highp float;
|
|
115
|
+
#else
|
|
116
|
+
precision mediump float;
|
|
117
|
+
#endif
|
|
118
|
+
|
|
119
|
+
uniform vec2 u_resolution;
|
|
120
|
+
uniform float u_time;
|
|
121
|
+
uniform vec2 u_mouse;
|
|
122
|
+
uniform float u_geometry;
|
|
123
|
+
uniform float u_gridDensity;
|
|
124
|
+
uniform float u_morphFactor;
|
|
125
|
+
uniform float u_chaos;
|
|
126
|
+
uniform float u_speed;
|
|
127
|
+
uniform float u_hue;
|
|
128
|
+
uniform float u_intensity;
|
|
129
|
+
uniform float u_saturation;
|
|
130
|
+
uniform float u_dimension;
|
|
131
|
+
uniform float u_rot4dXY;
|
|
132
|
+
uniform float u_rot4dXZ;
|
|
133
|
+
uniform float u_rot4dYZ;
|
|
134
|
+
uniform float u_rot4dXW;
|
|
135
|
+
uniform float u_rot4dYW;
|
|
136
|
+
uniform float u_rot4dZW;
|
|
137
|
+
uniform float u_mouseIntensity;
|
|
138
|
+
uniform float u_clickIntensity;
|
|
139
|
+
uniform float u_bass;
|
|
140
|
+
uniform float u_mid;
|
|
141
|
+
uniform float u_high;
|
|
142
|
+
|
|
143
|
+
mat4 rotateXY(float theta) {
|
|
144
|
+
float c = cos(theta); float s = sin(theta);
|
|
145
|
+
return mat4(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
146
|
+
}
|
|
147
|
+
mat4 rotateXZ(float theta) {
|
|
148
|
+
float c = cos(theta); float s = sin(theta);
|
|
149
|
+
return mat4(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
|
|
150
|
+
}
|
|
151
|
+
mat4 rotateYZ(float theta) {
|
|
152
|
+
float c = cos(theta); float s = sin(theta);
|
|
153
|
+
return mat4(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
|
|
154
|
+
}
|
|
155
|
+
mat4 rotateXW(float theta) {
|
|
156
|
+
float c = cos(theta); float s = sin(theta);
|
|
157
|
+
return mat4(c, 0, 0, -s, 0, 1, 0, 0, 0, 0, 1, 0, s, 0, 0, c);
|
|
158
|
+
}
|
|
159
|
+
mat4 rotateYW(float theta) {
|
|
160
|
+
float c = cos(theta); float s = sin(theta);
|
|
161
|
+
return mat4(1, 0, 0, 0, 0, c, 0, -s, 0, 0, 1, 0, 0, s, 0, c);
|
|
162
|
+
}
|
|
163
|
+
mat4 rotateZW(float theta) {
|
|
164
|
+
float c = cos(theta); float s = sin(theta);
|
|
165
|
+
return mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, c, -s, 0, 0, s, c);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
vec3 project4Dto3D(vec4 p) {
|
|
169
|
+
float w = 2.5 / (2.5 + p.w);
|
|
170
|
+
return vec3(p.x * w, p.y * w, p.z * w);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
vec3 warpHypersphereCore(vec3 p, int geometryIndex) {
|
|
174
|
+
float radius = length(p);
|
|
175
|
+
float morphBlend = clamp(u_morphFactor * 0.6 + (u_dimension - 3.0) * 0.25, 0.0, 2.0);
|
|
176
|
+
float w = sin(radius * (1.3 + float(geometryIndex) * 0.12) + u_time * 0.0008 * u_speed);
|
|
177
|
+
w *= (0.4 + morphBlend * 0.45);
|
|
178
|
+
vec4 p4d = vec4(p * (1.0 + morphBlend * 0.2), w);
|
|
179
|
+
p4d = rotateXY(u_rot4dXY) * rotateXZ(u_rot4dXZ) * rotateYZ(u_rot4dYZ) *
|
|
180
|
+
rotateXW(u_rot4dXW) * rotateYW(u_rot4dYW) * rotateZW(u_rot4dZW) * p4d;
|
|
181
|
+
vec3 projected = project4Dto3D(p4d);
|
|
182
|
+
return mix(p, projected, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
vec3 warpHypertetraCore(vec3 p, int geometryIndex) {
|
|
186
|
+
vec3 c1 = normalize(vec3(1.0, 1.0, 1.0));
|
|
187
|
+
vec3 c2 = normalize(vec3(-1.0, -1.0, 1.0));
|
|
188
|
+
vec3 c3 = normalize(vec3(-1.0, 1.0, -1.0));
|
|
189
|
+
vec3 c4 = normalize(vec3(1.0, -1.0, -1.0));
|
|
190
|
+
float morphBlend = clamp(u_morphFactor * 0.8 + (u_dimension - 3.0) * 0.2, 0.0, 2.0);
|
|
191
|
+
float basisMix = dot(p, c1) * 0.14 + dot(p, c2) * 0.1 + dot(p, c3) * 0.08;
|
|
192
|
+
float w = sin(basisMix * 5.5 + u_time * 0.0009 * u_speed) * cos(dot(p, c4) * 4.2 - u_time * 0.0007 * u_speed);
|
|
193
|
+
w *= (0.5 + morphBlend * 0.4);
|
|
194
|
+
vec3 offset = vec3(dot(p, c1), dot(p, c2), dot(p, c3)) * 0.1 * morphBlend;
|
|
195
|
+
vec4 p4d = vec4(p + offset, w);
|
|
196
|
+
p4d = rotateXY(u_rot4dXY) * rotateXZ(u_rot4dXZ) * rotateYZ(u_rot4dYZ) *
|
|
197
|
+
rotateXW(u_rot4dXW) * rotateYW(u_rot4dYW) * rotateZW(u_rot4dZW) * p4d;
|
|
198
|
+
vec3 projected = project4Dto3D(p4d);
|
|
199
|
+
float planeInfluence = min(min(abs(dot(p, c1)), abs(dot(p, c2))), min(abs(dot(p, c3)), abs(dot(p, c4))));
|
|
200
|
+
vec3 blended = mix(p, projected, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
|
|
201
|
+
return mix(blended, blended * (1.0 - planeInfluence * 0.55), 0.2 + morphBlend * 0.2);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
vec3 applyCoreWarp(vec3 p, float geometryType) {
|
|
205
|
+
float coreFloat = floor(geometryType / 8.0);
|
|
206
|
+
int coreIndex = int(clamp(coreFloat, 0.0, 2.0));
|
|
207
|
+
int geometryIndex = int(mod(geometryType, 8.0));
|
|
208
|
+
if (coreIndex == 1) return warpHypersphereCore(p, geometryIndex);
|
|
209
|
+
if (coreIndex == 2) return warpHypertetraCore(p, geometryIndex);
|
|
210
|
+
return p;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
float tetrahedronLattice(vec3 p, float gridSize) {
|
|
214
|
+
vec3 q = fract(p * gridSize) - 0.5;
|
|
215
|
+
float d1 = length(q);
|
|
216
|
+
float d2 = length(q - vec3(0.4, 0.0, 0.0));
|
|
217
|
+
float d3 = length(q - vec3(0.0, 0.4, 0.0));
|
|
218
|
+
float d4 = length(q - vec3(0.0, 0.0, 0.4));
|
|
219
|
+
float vertices = 1.0 - smoothstep(0.0, 0.04, min(min(d1, d2), min(d3, d4)));
|
|
220
|
+
float edges = max(max(
|
|
221
|
+
1.0 - smoothstep(0.0, 0.02, abs(length(q.xy) - 0.2)),
|
|
222
|
+
1.0 - smoothstep(0.0, 0.02, abs(length(q.yz) - 0.2))),
|
|
223
|
+
1.0 - smoothstep(0.0, 0.02, abs(length(q.xz) - 0.2)));
|
|
224
|
+
return max(vertices, edges * 0.5);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
float hypercubeLattice(vec3 p, float gridSize) {
|
|
228
|
+
vec3 grid = fract(p * gridSize);
|
|
229
|
+
vec3 edges = min(grid, 1.0 - grid);
|
|
230
|
+
float minEdge = min(min(edges.x, edges.y), edges.z);
|
|
231
|
+
float lattice = 1.0 - smoothstep(0.0, 0.03, minEdge);
|
|
232
|
+
vec3 centers = abs(grid - 0.5);
|
|
233
|
+
float maxCenter = max(max(centers.x, centers.y), centers.z);
|
|
234
|
+
float vertices = 1.0 - smoothstep(0.45, 0.5, maxCenter);
|
|
235
|
+
return max(lattice * 0.7, vertices);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
float sphereLattice(vec3 p, float gridSize) {
|
|
239
|
+
vec3 cell = fract(p * gridSize) - 0.5;
|
|
240
|
+
float sphere = 1.0 - smoothstep(0.15, 0.25, length(cell));
|
|
241
|
+
float ringRadius = length(cell.xy);
|
|
242
|
+
float rings = max(
|
|
243
|
+
1.0 - smoothstep(0.0, 0.02, abs(ringRadius - 0.3)),
|
|
244
|
+
1.0 - smoothstep(0.0, 0.02, abs(ringRadius - 0.2)));
|
|
245
|
+
return max(sphere, rings * 0.6);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
float torusLattice(vec3 p, float gridSize) {
|
|
249
|
+
vec3 cell = fract(p * gridSize) - 0.5;
|
|
250
|
+
float toroidalDist = length(vec2(length(cell.xy) - 0.3, cell.z));
|
|
251
|
+
return 1.0 - smoothstep(0.08, 0.12, toroidalDist);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
float kleinLattice(vec3 p, float gridSize) {
|
|
255
|
+
vec3 cell = fract(p * gridSize) - 0.5;
|
|
256
|
+
float u = atan(cell.y, cell.x) / 3.14159 + 1.0;
|
|
257
|
+
float x = (2.0 + cos(u * 0.5)) * cos(u);
|
|
258
|
+
float y = (2.0 + cos(u * 0.5)) * sin(u);
|
|
259
|
+
float z = sin(u * 0.5) + cell.z + 0.5;
|
|
260
|
+
float dist = length(cell - vec3(x, y, z) * 0.1);
|
|
261
|
+
return 1.0 - smoothstep(0.1, 0.15, dist);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
float fractalLattice(vec3 p, float gridSize) {
|
|
265
|
+
vec3 cell = fract(p * gridSize);
|
|
266
|
+
cell = abs(cell * 2.0 - 1.0);
|
|
267
|
+
float dist = length(max(abs(cell) - 0.3, 0.0));
|
|
268
|
+
for(int i = 0; i < 3; i++) {
|
|
269
|
+
cell = abs(cell * 2.0 - 1.0);
|
|
270
|
+
float subdist = length(max(abs(cell) - 0.3, 0.0)) / pow(2.0, float(i + 1));
|
|
271
|
+
dist = min(dist, subdist);
|
|
272
|
+
}
|
|
273
|
+
return 1.0 - smoothstep(0.0, 0.05, dist);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
float waveLattice(vec3 p, float gridSize) {
|
|
277
|
+
float time = u_time * 0.001 * u_speed;
|
|
278
|
+
vec3 cell = fract(p * gridSize) - 0.5;
|
|
279
|
+
float wave1 = sin(p.x * gridSize * 2.0 + time * 2.0);
|
|
280
|
+
float wave2 = sin(p.y * gridSize * 1.8 + time * 1.5);
|
|
281
|
+
float wave3 = sin(p.z * gridSize * 2.2 + time * 1.8);
|
|
282
|
+
float interference = (wave1 + wave2 + wave3) / 3.0;
|
|
283
|
+
float amplitude = 1.0 - length(cell) * 2.0;
|
|
284
|
+
return max(0.0, interference * amplitude);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
float crystalLattice(vec3 p, float gridSize) {
|
|
288
|
+
vec3 cell = fract(p * gridSize) - 0.5;
|
|
289
|
+
float crystal = max(max(abs(cell.x) + abs(cell.y), abs(cell.y) + abs(cell.z)), abs(cell.x) + abs(cell.z));
|
|
290
|
+
crystal = 1.0 - smoothstep(0.3, 0.4, crystal);
|
|
291
|
+
float faces = max(max(
|
|
292
|
+
1.0 - smoothstep(0.0, 0.02, abs(abs(cell.x) - 0.35)),
|
|
293
|
+
1.0 - smoothstep(0.0, 0.02, abs(abs(cell.y) - 0.35))),
|
|
294
|
+
1.0 - smoothstep(0.0, 0.02, abs(abs(cell.z) - 0.35)));
|
|
295
|
+
return max(crystal, faces * 0.5);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
float geometryFunction(vec4 p) {
|
|
299
|
+
int geomType = int(mod(u_geometry, 8.0));
|
|
300
|
+
vec3 p3d = project4Dto3D(p);
|
|
301
|
+
vec3 warped = applyCoreWarp(p3d, u_geometry);
|
|
302
|
+
float gridSize = (u_gridDensity + u_bass * 40.0) * 0.08;
|
|
303
|
+
|
|
304
|
+
if (geomType == 0) return tetrahedronLattice(warped, gridSize) * u_morphFactor;
|
|
305
|
+
else if (geomType == 1) return hypercubeLattice(warped, gridSize) * u_morphFactor;
|
|
306
|
+
else if (geomType == 2) return sphereLattice(warped, gridSize) * u_morphFactor;
|
|
307
|
+
else if (geomType == 3) return torusLattice(warped, gridSize) * u_morphFactor;
|
|
308
|
+
else if (geomType == 4) return kleinLattice(warped, gridSize) * u_morphFactor;
|
|
309
|
+
else if (geomType == 5) return fractalLattice(warped, gridSize) * u_morphFactor;
|
|
310
|
+
else if (geomType == 6) return waveLattice(warped, gridSize) * u_morphFactor;
|
|
311
|
+
else return crystalLattice(warped, gridSize) * u_morphFactor;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
vec3 hsv2rgb(vec3 c) {
|
|
315
|
+
vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);
|
|
316
|
+
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
|
317
|
+
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
void main() {
|
|
321
|
+
vec2 uv = (gl_FragCoord.xy - u_resolution.xy * 0.5) / min(u_resolution.x, u_resolution.y);
|
|
322
|
+
float timeSpeed = u_time * 0.0001 * u_speed;
|
|
323
|
+
vec4 pos = vec4(uv * 3.0, sin(timeSpeed * 3.0), cos(timeSpeed * 2.0));
|
|
324
|
+
pos.xy += (u_mouse - 0.5) * u_mouseIntensity * 2.0;
|
|
325
|
+
|
|
326
|
+
pos = rotateXY(u_rot4dXY) * rotateXZ(u_rot4dXZ) * rotateYZ(u_rot4dYZ) *
|
|
327
|
+
rotateXW(u_rot4dXW) * rotateYW(u_rot4dYW) * rotateZW(u_rot4dZW) * pos;
|
|
328
|
+
|
|
329
|
+
float value = geometryFunction(pos);
|
|
330
|
+
float noise = sin(pos.x * 7.0) * cos(pos.y * 11.0) * sin(pos.z * 13.0);
|
|
331
|
+
value += noise * (u_chaos + u_high * 0.6);
|
|
332
|
+
|
|
333
|
+
float geometryIntensity = 1.0 - clamp(abs(value * 0.8), 0.0, 1.0);
|
|
334
|
+
geometryIntensity = pow(geometryIntensity, 1.5);
|
|
335
|
+
geometryIntensity += u_clickIntensity * 0.3;
|
|
336
|
+
|
|
337
|
+
float shimmer = sin(uv.x * 20.0 + timeSpeed * 5.0) * cos(uv.y * 15.0 + timeSpeed * 3.0) * 0.1;
|
|
338
|
+
geometryIntensity += shimmer * geometryIntensity;
|
|
339
|
+
|
|
340
|
+
float hueShift = u_hue / 360.0 + u_mid * 0.3;
|
|
341
|
+
vec3 color = hsv2rgb(vec3(hueShift + value * 0.1, u_saturation, u_intensity));
|
|
342
|
+
color *= geometryIntensity;
|
|
343
|
+
|
|
344
|
+
gl_FragColor = vec4(color, geometryIntensity * u_intensity);
|
|
345
|
+
}`);
|
|
346
|
+
|
|
347
|
+
const program = gl.createProgram();
|
|
348
|
+
gl.attachShader(program, vs);
|
|
349
|
+
gl.attachShader(program, fs);
|
|
350
|
+
gl.linkProgram(program);
|
|
351
|
+
|
|
352
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
353
|
+
console.error('Link error:', gl.getProgramInfoLog(program));
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
gl.useProgram(program);
|
|
357
|
+
|
|
358
|
+
// Fullscreen quad
|
|
359
|
+
const positions = new Float32Array([-1,-1, 1,-1, -1,1, 1,1]);
|
|
360
|
+
const buffer = gl.createBuffer();
|
|
361
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
362
|
+
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
|
|
363
|
+
|
|
364
|
+
const posLoc = gl.getAttribLocation(program, 'a_position');
|
|
365
|
+
gl.enableVertexAttribArray(posLoc);
|
|
366
|
+
gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
|
|
367
|
+
|
|
368
|
+
// Get uniform locations
|
|
369
|
+
const uniforms = {};
|
|
370
|
+
const uniformNames = [
|
|
371
|
+
'u_time', 'u_resolution', 'u_mouse', 'u_geometry',
|
|
372
|
+
'u_gridDensity', 'u_morphFactor', 'u_chaos', 'u_speed',
|
|
373
|
+
'u_hue', 'u_intensity', 'u_saturation', 'u_dimension',
|
|
374
|
+
'u_rot4dXY', 'u_rot4dXZ', 'u_rot4dYZ',
|
|
375
|
+
'u_rot4dXW', 'u_rot4dYW', 'u_rot4dZW',
|
|
376
|
+
'u_mouseIntensity', 'u_clickIntensity',
|
|
377
|
+
'u_bass', 'u_mid', 'u_high'
|
|
378
|
+
];
|
|
379
|
+
uniformNames.forEach(name => {
|
|
380
|
+
uniforms[name] = gl.getUniformLocation(program, name);
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// State
|
|
384
|
+
let mouseX = 0.5, mouseY = 0.5, mouseIntensity = 0, clickIntensity = 0;
|
|
385
|
+
let bass = 0, mid = 0, high = 0;
|
|
386
|
+
let audioContext, analyser, dataArray, audioEnabled = false;
|
|
387
|
+
const startTime = performance.now();
|
|
388
|
+
|
|
389
|
+
// Mouse tracking
|
|
390
|
+
document.addEventListener('mousemove', e => {
|
|
391
|
+
mouseX = e.clientX / window.innerWidth;
|
|
392
|
+
mouseY = 1 - e.clientY / window.innerHeight;
|
|
393
|
+
mouseIntensity = Math.min(1, mouseIntensity + 0.1);
|
|
394
|
+
});
|
|
395
|
+
document.addEventListener('click', () => {
|
|
396
|
+
clickIntensity = 1;
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// Audio setup
|
|
400
|
+
window.toggleAudio = async function() {
|
|
401
|
+
if (audioEnabled) {
|
|
402
|
+
audioEnabled = false;
|
|
403
|
+
document.querySelector('.audio-btn').textContent = '🎵 Enable Audio';
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
try {
|
|
408
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
409
|
+
audioContext = new AudioContext();
|
|
410
|
+
analyser = audioContext.createAnalyser();
|
|
411
|
+
analyser.fftSize = 256;
|
|
412
|
+
const source = audioContext.createMediaStreamSource(stream);
|
|
413
|
+
source.connect(analyser);
|
|
414
|
+
dataArray = new Uint8Array(analyser.frequencyBinCount);
|
|
415
|
+
audioEnabled = true;
|
|
416
|
+
document.querySelector('.audio-btn').textContent = '🔊 Audio Active';
|
|
417
|
+
} catch (e) {
|
|
418
|
+
console.log('Audio not available:', e);
|
|
419
|
+
alert('Could not access microphone');
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
function updateAudio() {
|
|
424
|
+
if (!audioEnabled || !analyser) return;
|
|
425
|
+
analyser.getByteFrequencyData(dataArray);
|
|
426
|
+
|
|
427
|
+
// Bass: 0-8, Mid: 8-32, High: 32-64
|
|
428
|
+
let bassSum = 0, midSum = 0, highSum = 0;
|
|
429
|
+
for (let i = 0; i < 8; i++) bassSum += dataArray[i];
|
|
430
|
+
for (let i = 8; i < 32; i++) midSum += dataArray[i];
|
|
431
|
+
for (let i = 32; i < 64; i++) highSum += dataArray[i];
|
|
432
|
+
|
|
433
|
+
bass = (bassSum / 8 / 255) * (CONFIG.reactivity?.audio?.sensitivity || 1);
|
|
434
|
+
mid = (midSum / 24 / 255) * (CONFIG.reactivity?.audio?.sensitivity || 1);
|
|
435
|
+
high = (highSum / 32 / 255) * (CONFIG.reactivity?.audio?.sensitivity || 1);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Resize
|
|
439
|
+
function resize() {
|
|
440
|
+
const dpr = Math.min(window.devicePixelRatio, 2);
|
|
441
|
+
canvas.width = window.innerWidth * dpr;
|
|
442
|
+
canvas.height = window.innerHeight * dpr;
|
|
443
|
+
gl.viewport(0, 0, canvas.width, canvas.height);
|
|
444
|
+
}
|
|
445
|
+
window.addEventListener('resize', resize);
|
|
446
|
+
resize();
|
|
447
|
+
|
|
448
|
+
// Render loop
|
|
449
|
+
function render() {
|
|
450
|
+
const time = performance.now() - startTime;
|
|
451
|
+
|
|
452
|
+
updateAudio();
|
|
453
|
+
mouseIntensity *= 0.95;
|
|
454
|
+
clickIntensity *= 0.92;
|
|
455
|
+
|
|
456
|
+
gl.uniform1f(uniforms.u_time, time);
|
|
457
|
+
gl.uniform2f(uniforms.u_resolution, canvas.width, canvas.height);
|
|
458
|
+
gl.uniform2f(uniforms.u_mouse, mouseX, mouseY);
|
|
459
|
+
gl.uniform1f(uniforms.u_geometry, CONFIG.geometry);
|
|
460
|
+
gl.uniform1f(uniforms.u_gridDensity, CONFIG.params.gridDensity);
|
|
461
|
+
gl.uniform1f(uniforms.u_morphFactor, CONFIG.params.morphFactor);
|
|
462
|
+
gl.uniform1f(uniforms.u_chaos, CONFIG.params.chaos);
|
|
463
|
+
gl.uniform1f(uniforms.u_speed, CONFIG.params.speed);
|
|
464
|
+
gl.uniform1f(uniforms.u_hue, CONFIG.params.hue);
|
|
465
|
+
gl.uniform1f(uniforms.u_intensity, CONFIG.params.intensity);
|
|
466
|
+
gl.uniform1f(uniforms.u_saturation, CONFIG.params.saturation || 0.8);
|
|
467
|
+
gl.uniform1f(uniforms.u_dimension, CONFIG.params.dimension || 3.5);
|
|
468
|
+
gl.uniform1f(uniforms.u_rot4dXY, CONFIG.params.rot4dXY || 0);
|
|
469
|
+
gl.uniform1f(uniforms.u_rot4dXZ, CONFIG.params.rot4dXZ || 0);
|
|
470
|
+
gl.uniform1f(uniforms.u_rot4dYZ, CONFIG.params.rot4dYZ || 0);
|
|
471
|
+
gl.uniform1f(uniforms.u_rot4dXW, CONFIG.params.rot4dXW || 0);
|
|
472
|
+
gl.uniform1f(uniforms.u_rot4dYW, CONFIG.params.rot4dYW || 0);
|
|
473
|
+
gl.uniform1f(uniforms.u_rot4dZW, CONFIG.params.rot4dZW || 0);
|
|
474
|
+
gl.uniform1f(uniforms.u_mouseIntensity, mouseIntensity);
|
|
475
|
+
gl.uniform1f(uniforms.u_clickIntensity, clickIntensity);
|
|
476
|
+
gl.uniform1f(uniforms.u_bass, bass);
|
|
477
|
+
gl.uniform1f(uniforms.u_mid, mid);
|
|
478
|
+
gl.uniform1f(uniforms.u_high, high);
|
|
479
|
+
|
|
480
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
481
|
+
requestAnimationFrame(render);
|
|
482
|
+
}
|
|
483
|
+
render();
|
|
484
|
+
|
|
485
|
+
console.log('VIB3+ QUANTUM visualization initialized');
|
|
486
|
+
console.log('Config:', CONFIG);
|
|
487
|
+
</script>
|
|
488
|
+
</body>
|
|
489
|
+
</html>
|