@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,519 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVGExporter - Export VIB3+ visualizations as SVG
|
|
3
|
+
*
|
|
4
|
+
* Generates optimized SVG output from geometry data with
|
|
5
|
+
* embedded metadata for validation and theming.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Vec4 } from '../math/Vec4.js';
|
|
9
|
+
import { Rotor4D } from '../math/Rotor4D.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Default export options
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_OPTIONS = {
|
|
15
|
+
width: 512,
|
|
16
|
+
height: 512,
|
|
17
|
+
strokeWidth: 1.5,
|
|
18
|
+
includeMetadata: true,
|
|
19
|
+
includeWatermark: false,
|
|
20
|
+
watermarkText: 'Created with VIB3+ Community',
|
|
21
|
+
backgroundColor: 'transparent',
|
|
22
|
+
precision: 3
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Geometry names for metadata
|
|
27
|
+
*/
|
|
28
|
+
const GEOMETRY_NAMES = [
|
|
29
|
+
'Tetrahedron', 'Hypercube', 'Sphere', 'Torus',
|
|
30
|
+
'Klein Bottle', 'Fractal', 'Wave', 'Crystal'
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Core type names
|
|
35
|
+
*/
|
|
36
|
+
const CORE_TYPES = ['Base', 'Hypersphere', 'Hypertetrahedron'];
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Export parameters to SVG format
|
|
40
|
+
*
|
|
41
|
+
* @param {object} params - VIB3+ parameters
|
|
42
|
+
* @param {object} options - Export options
|
|
43
|
+
* @returns {string} SVG content
|
|
44
|
+
*/
|
|
45
|
+
export function exportSVG(params, options = {}) {
|
|
46
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
47
|
+
const { width, height, precision } = opts;
|
|
48
|
+
|
|
49
|
+
// Extract parameters
|
|
50
|
+
const system = params.system || 'quantum';
|
|
51
|
+
const geometry = params.geometry ?? 0;
|
|
52
|
+
const hue = params.hue ?? 200;
|
|
53
|
+
const saturation = params.saturation ?? 0.7;
|
|
54
|
+
const intensity = params.intensity ?? 0.8;
|
|
55
|
+
const gridDensity = params.gridDensity ?? 16;
|
|
56
|
+
const dimension = params.dimension ?? 3.5;
|
|
57
|
+
|
|
58
|
+
// Calculate derived values
|
|
59
|
+
const baseIndex = geometry % 8;
|
|
60
|
+
const coreIndex = Math.floor(geometry / 8);
|
|
61
|
+
const geometryName = GEOMETRY_NAMES[baseIndex] || 'Unknown';
|
|
62
|
+
const coreType = CORE_TYPES[coreIndex] || 'Base';
|
|
63
|
+
|
|
64
|
+
// Build rotation from parameters
|
|
65
|
+
const rotor = Rotor4D.fromParameters(params);
|
|
66
|
+
|
|
67
|
+
// Generate geometry points
|
|
68
|
+
const points = generateGeometryPoints(params, opts);
|
|
69
|
+
|
|
70
|
+
// Project to 2D
|
|
71
|
+
const projectedPoints = projectPoints(points, rotor, dimension, width, height);
|
|
72
|
+
|
|
73
|
+
// Generate SVG paths
|
|
74
|
+
const paths = generatePaths(projectedPoints, params, opts);
|
|
75
|
+
|
|
76
|
+
// Build SVG
|
|
77
|
+
const svg = buildSVG({
|
|
78
|
+
width,
|
|
79
|
+
height,
|
|
80
|
+
paths,
|
|
81
|
+
params,
|
|
82
|
+
opts,
|
|
83
|
+
metadata: {
|
|
84
|
+
system,
|
|
85
|
+
geometry,
|
|
86
|
+
geometryName,
|
|
87
|
+
coreType,
|
|
88
|
+
hue,
|
|
89
|
+
saturation,
|
|
90
|
+
intensity
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return svg;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Generate geometry points based on parameters
|
|
99
|
+
*/
|
|
100
|
+
function generateGeometryPoints(params, opts) {
|
|
101
|
+
const points = [];
|
|
102
|
+
const density = params.gridDensity ?? 16;
|
|
103
|
+
const geometry = params.geometry ?? 0;
|
|
104
|
+
const baseIndex = geometry % 8;
|
|
105
|
+
|
|
106
|
+
// Generate base geometry points
|
|
107
|
+
switch (baseIndex) {
|
|
108
|
+
case 0: // Tetrahedron
|
|
109
|
+
generateTetrahedronPoints(points, density);
|
|
110
|
+
break;
|
|
111
|
+
case 1: // Hypercube
|
|
112
|
+
generateHypercubePoints(points, density);
|
|
113
|
+
break;
|
|
114
|
+
case 2: // Sphere
|
|
115
|
+
generateSpherePoints(points, density);
|
|
116
|
+
break;
|
|
117
|
+
case 3: // Torus
|
|
118
|
+
generateTorusPoints(points, density);
|
|
119
|
+
break;
|
|
120
|
+
case 4: // Klein Bottle
|
|
121
|
+
generateKleinBottlePoints(points, density);
|
|
122
|
+
break;
|
|
123
|
+
case 5: // Fractal
|
|
124
|
+
generateFractalPoints(points, density);
|
|
125
|
+
break;
|
|
126
|
+
case 6: // Wave
|
|
127
|
+
generateWavePoints(points, density);
|
|
128
|
+
break;
|
|
129
|
+
case 7: // Crystal
|
|
130
|
+
generateCrystalPoints(points, density);
|
|
131
|
+
break;
|
|
132
|
+
default:
|
|
133
|
+
generateSpherePoints(points, density);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return points;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Generate tetrahedron vertices and edges
|
|
141
|
+
*/
|
|
142
|
+
function generateTetrahedronPoints(points, density) {
|
|
143
|
+
// Regular tetrahedron vertices in 4D
|
|
144
|
+
const vertices = [
|
|
145
|
+
new Vec4(1, 1, 1, 0),
|
|
146
|
+
new Vec4(1, -1, -1, 0),
|
|
147
|
+
new Vec4(-1, 1, -1, 0),
|
|
148
|
+
new Vec4(-1, -1, 1, 0)
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
// Normalize to unit sphere
|
|
152
|
+
vertices.forEach(v => v.normalizeInPlace());
|
|
153
|
+
|
|
154
|
+
// Add edge midpoints for smoother curves
|
|
155
|
+
for (let i = 0; i < vertices.length; i++) {
|
|
156
|
+
points.push(vertices[i].clone());
|
|
157
|
+
for (let j = i + 1; j < vertices.length; j++) {
|
|
158
|
+
const steps = Math.max(2, Math.floor(density / 4));
|
|
159
|
+
for (let t = 1; t < steps; t++) {
|
|
160
|
+
const lerped = vertices[i].lerp(vertices[j], t / steps);
|
|
161
|
+
lerped.normalizeInPlace();
|
|
162
|
+
points.push(lerped);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Generate hypercube (tesseract) points
|
|
170
|
+
*/
|
|
171
|
+
function generateHypercubePoints(points, density) {
|
|
172
|
+
const scale = 0.5;
|
|
173
|
+
// All 16 vertices of a tesseract
|
|
174
|
+
for (let x = -1; x <= 1; x += 2) {
|
|
175
|
+
for (let y = -1; y <= 1; y += 2) {
|
|
176
|
+
for (let z = -1; z <= 1; z += 2) {
|
|
177
|
+
for (let w = -1; w <= 1; w += 2) {
|
|
178
|
+
points.push(new Vec4(x * scale, y * scale, z * scale, w * scale));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Add edge points
|
|
185
|
+
const steps = Math.max(2, Math.floor(density / 8));
|
|
186
|
+
const vertices = [...points];
|
|
187
|
+
for (let i = 0; i < vertices.length; i++) {
|
|
188
|
+
for (let j = i + 1; j < vertices.length; j++) {
|
|
189
|
+
// Only connect adjacent vertices (differ in one coordinate)
|
|
190
|
+
const diff = Math.abs(vertices[i].x - vertices[j].x) +
|
|
191
|
+
Math.abs(vertices[i].y - vertices[j].y) +
|
|
192
|
+
Math.abs(vertices[i].z - vertices[j].z) +
|
|
193
|
+
Math.abs(vertices[i].w - vertices[j].w);
|
|
194
|
+
if (Math.abs(diff - 1) < 0.1) {
|
|
195
|
+
for (let t = 1; t < steps; t++) {
|
|
196
|
+
points.push(vertices[i].lerp(vertices[j], t / steps));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Generate sphere points
|
|
205
|
+
*/
|
|
206
|
+
function generateSpherePoints(points, density) {
|
|
207
|
+
const latSteps = Math.max(4, density);
|
|
208
|
+
const lonSteps = Math.max(8, density * 2);
|
|
209
|
+
|
|
210
|
+
for (let lat = 0; lat <= latSteps; lat++) {
|
|
211
|
+
const theta = (lat / latSteps) * Math.PI;
|
|
212
|
+
const sinTheta = Math.sin(theta);
|
|
213
|
+
const cosTheta = Math.cos(theta);
|
|
214
|
+
|
|
215
|
+
for (let lon = 0; lon < lonSteps; lon++) {
|
|
216
|
+
const phi = (lon / lonSteps) * Math.PI * 2;
|
|
217
|
+
const x = sinTheta * Math.cos(phi);
|
|
218
|
+
const y = sinTheta * Math.sin(phi);
|
|
219
|
+
const z = cosTheta;
|
|
220
|
+
points.push(new Vec4(x * 0.8, y * 0.8, z * 0.8, 0));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Generate torus points
|
|
227
|
+
*/
|
|
228
|
+
function generateTorusPoints(points, density) {
|
|
229
|
+
const majorRadius = 0.6;
|
|
230
|
+
const minorRadius = 0.25;
|
|
231
|
+
const majorSteps = Math.max(8, density);
|
|
232
|
+
const minorSteps = Math.max(6, Math.floor(density * 0.75));
|
|
233
|
+
|
|
234
|
+
for (let i = 0; i < majorSteps; i++) {
|
|
235
|
+
const theta = (i / majorSteps) * Math.PI * 2;
|
|
236
|
+
for (let j = 0; j < minorSteps; j++) {
|
|
237
|
+
const phi = (j / minorSteps) * Math.PI * 2;
|
|
238
|
+
const x = (majorRadius + minorRadius * Math.cos(phi)) * Math.cos(theta);
|
|
239
|
+
const y = (majorRadius + minorRadius * Math.cos(phi)) * Math.sin(theta);
|
|
240
|
+
const z = minorRadius * Math.sin(phi);
|
|
241
|
+
points.push(new Vec4(x, y, z, 0));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Generate Klein bottle points (immersion in 3D)
|
|
248
|
+
*/
|
|
249
|
+
function generateKleinBottlePoints(points, density) {
|
|
250
|
+
const steps = Math.max(8, density);
|
|
251
|
+
|
|
252
|
+
for (let u = 0; u < steps; u++) {
|
|
253
|
+
const uAngle = (u / steps) * Math.PI * 2;
|
|
254
|
+
for (let v = 0; v < steps; v++) {
|
|
255
|
+
const vAngle = (v / steps) * Math.PI * 2;
|
|
256
|
+
|
|
257
|
+
// Figure-8 immersion
|
|
258
|
+
const r = 0.4;
|
|
259
|
+
const x = (r + Math.cos(uAngle / 2) * Math.sin(vAngle) - Math.sin(uAngle / 2) * Math.sin(2 * vAngle)) * Math.cos(uAngle);
|
|
260
|
+
const y = (r + Math.cos(uAngle / 2) * Math.sin(vAngle) - Math.sin(uAngle / 2) * Math.sin(2 * vAngle)) * Math.sin(uAngle);
|
|
261
|
+
const z = Math.sin(uAngle / 2) * Math.sin(vAngle) + Math.cos(uAngle / 2) * Math.sin(2 * vAngle);
|
|
262
|
+
|
|
263
|
+
points.push(new Vec4(x * 0.8, y * 0.8, z * 0.5, 0));
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Generate fractal points (Sierpinski-like)
|
|
270
|
+
*/
|
|
271
|
+
function generateFractalPoints(points, density) {
|
|
272
|
+
const iterations = Math.min(4, Math.floor(Math.log2(density)));
|
|
273
|
+
const vertices = [
|
|
274
|
+
new Vec4(0, 0.8, 0, 0),
|
|
275
|
+
new Vec4(-0.7, -0.4, 0, 0),
|
|
276
|
+
new Vec4(0.7, -0.4, 0, 0),
|
|
277
|
+
new Vec4(0, 0, 0.7, 0)
|
|
278
|
+
];
|
|
279
|
+
|
|
280
|
+
function subdivide(v1, v2, v3, v4, depth) {
|
|
281
|
+
if (depth === 0) {
|
|
282
|
+
points.push(v1.clone(), v2.clone(), v3.clone(), v4.clone());
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const m12 = v1.lerp(v2, 0.5);
|
|
287
|
+
const m13 = v1.lerp(v3, 0.5);
|
|
288
|
+
const m14 = v1.lerp(v4, 0.5);
|
|
289
|
+
const m23 = v2.lerp(v3, 0.5);
|
|
290
|
+
const m24 = v2.lerp(v4, 0.5);
|
|
291
|
+
const m34 = v3.lerp(v4, 0.5);
|
|
292
|
+
|
|
293
|
+
subdivide(v1, m12, m13, m14, depth - 1);
|
|
294
|
+
subdivide(m12, v2, m23, m24, depth - 1);
|
|
295
|
+
subdivide(m13, m23, v3, m34, depth - 1);
|
|
296
|
+
subdivide(m14, m24, m34, v4, depth - 1);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
subdivide(vertices[0], vertices[1], vertices[2], vertices[3], iterations);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Generate wave points
|
|
304
|
+
*/
|
|
305
|
+
function generateWavePoints(points, density) {
|
|
306
|
+
const steps = Math.max(8, density);
|
|
307
|
+
const amplitude = 0.3;
|
|
308
|
+
const frequency = 3;
|
|
309
|
+
|
|
310
|
+
for (let i = 0; i < steps; i++) {
|
|
311
|
+
for (let j = 0; j < steps; j++) {
|
|
312
|
+
const u = (i / steps - 0.5) * 2;
|
|
313
|
+
const v = (j / steps - 0.5) * 2;
|
|
314
|
+
const r = Math.sqrt(u * u + v * v);
|
|
315
|
+
const z = amplitude * Math.sin(r * frequency * Math.PI) * Math.exp(-r);
|
|
316
|
+
points.push(new Vec4(u * 0.8, v * 0.8, z, 0));
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Generate crystal (octahedron) points
|
|
323
|
+
*/
|
|
324
|
+
function generateCrystalPoints(points, density) {
|
|
325
|
+
const vertices = [
|
|
326
|
+
new Vec4(0, 0.8, 0, 0),
|
|
327
|
+
new Vec4(0, -0.8, 0, 0),
|
|
328
|
+
new Vec4(0.8, 0, 0, 0),
|
|
329
|
+
new Vec4(-0.8, 0, 0, 0),
|
|
330
|
+
new Vec4(0, 0, 0.8, 0),
|
|
331
|
+
new Vec4(0, 0, -0.8, 0)
|
|
332
|
+
];
|
|
333
|
+
|
|
334
|
+
vertices.forEach(v => points.push(v.clone()));
|
|
335
|
+
|
|
336
|
+
const steps = Math.max(2, Math.floor(density / 4));
|
|
337
|
+
for (let i = 0; i < vertices.length; i++) {
|
|
338
|
+
for (let j = i + 1; j < vertices.length; j++) {
|
|
339
|
+
// Connect non-opposite vertices
|
|
340
|
+
if (vertices[i].dot(vertices[j]) !== -vertices[i].lengthSquared()) {
|
|
341
|
+
for (let t = 1; t < steps; t++) {
|
|
342
|
+
points.push(vertices[i].lerp(vertices[j], t / steps));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Project 4D points to 2D screen coordinates
|
|
351
|
+
*/
|
|
352
|
+
function projectPoints(points, rotor, dimension, width, height) {
|
|
353
|
+
const projected = [];
|
|
354
|
+
const centerX = width / 2;
|
|
355
|
+
const centerY = height / 2;
|
|
356
|
+
const scale = Math.min(width, height) * 0.4;
|
|
357
|
+
|
|
358
|
+
for (const point of points) {
|
|
359
|
+
// Apply 4D rotation
|
|
360
|
+
const rotated = rotor.rotate(point);
|
|
361
|
+
|
|
362
|
+
// Project to 3D (perspective from W)
|
|
363
|
+
const proj3d = rotated.projectPerspective(dimension);
|
|
364
|
+
|
|
365
|
+
// Project to 2D (simple orthographic for clean SVG)
|
|
366
|
+
const x = centerX + proj3d.x * scale;
|
|
367
|
+
const y = centerY - proj3d.y * scale; // Flip Y for SVG coordinates
|
|
368
|
+
const depth = proj3d.z; // Keep depth for styling
|
|
369
|
+
|
|
370
|
+
projected.push({ x, y, depth, original: point });
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return projected;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Generate SVG path elements from projected points
|
|
378
|
+
*/
|
|
379
|
+
function generatePaths(projectedPoints, params, opts) {
|
|
380
|
+
const { precision } = opts;
|
|
381
|
+
const hue = params.hue ?? 200;
|
|
382
|
+
const saturation = params.saturation ?? 0.7;
|
|
383
|
+
const intensity = params.intensity ?? 0.8;
|
|
384
|
+
const chaos = params.chaos ?? 0;
|
|
385
|
+
|
|
386
|
+
// Sort by depth for proper layering
|
|
387
|
+
const sorted = [...projectedPoints].sort((a, b) => a.depth - b.depth);
|
|
388
|
+
|
|
389
|
+
const paths = [];
|
|
390
|
+
|
|
391
|
+
// Generate circles for each point
|
|
392
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
393
|
+
const point = sorted[i];
|
|
394
|
+
const depthFactor = (point.depth + 1) / 2; // Normalize depth to 0-1
|
|
395
|
+
const radius = 2 + depthFactor * 3 + chaos * Math.random() * 2;
|
|
396
|
+
const pointHue = (hue + depthFactor * 60) % 360;
|
|
397
|
+
const lightness = 40 + intensity * 30 + depthFactor * 20;
|
|
398
|
+
const alpha = 0.5 + depthFactor * 0.5;
|
|
399
|
+
|
|
400
|
+
paths.push({
|
|
401
|
+
type: 'circle',
|
|
402
|
+
cx: point.x.toFixed(precision),
|
|
403
|
+
cy: point.y.toFixed(precision),
|
|
404
|
+
r: radius.toFixed(precision),
|
|
405
|
+
fill: `hsla(${pointHue.toFixed(0)}, ${(saturation * 100).toFixed(0)}%, ${lightness.toFixed(0)}%, ${alpha.toFixed(2)})`
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Connect nearby points with lines
|
|
410
|
+
const strokeHue = (hue + 180) % 360;
|
|
411
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
412
|
+
for (let j = i + 1; j < Math.min(i + 5, sorted.length); j++) {
|
|
413
|
+
const p1 = sorted[i];
|
|
414
|
+
const p2 = sorted[j];
|
|
415
|
+
const dist = Math.hypot(p2.x - p1.x, p2.y - p1.y);
|
|
416
|
+
|
|
417
|
+
if (dist < 50 && dist > 5) {
|
|
418
|
+
const alpha = Math.max(0.1, 0.4 - dist / 150);
|
|
419
|
+
paths.push({
|
|
420
|
+
type: 'line',
|
|
421
|
+
x1: p1.x.toFixed(precision),
|
|
422
|
+
y1: p1.y.toFixed(precision),
|
|
423
|
+
x2: p2.x.toFixed(precision),
|
|
424
|
+
y2: p2.y.toFixed(precision),
|
|
425
|
+
stroke: `hsla(${strokeHue}, ${(saturation * 80).toFixed(0)}%, 60%, ${alpha.toFixed(2)})`,
|
|
426
|
+
strokeWidth: (opts.strokeWidth * alpha).toFixed(precision)
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return paths;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Build final SVG string
|
|
437
|
+
*/
|
|
438
|
+
function buildSVG({ width, height, paths, params, opts, metadata }) {
|
|
439
|
+
const { includeMetadata, includeWatermark, watermarkText, backgroundColor, precision } = opts;
|
|
440
|
+
|
|
441
|
+
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}"`;
|
|
442
|
+
|
|
443
|
+
if (includeMetadata) {
|
|
444
|
+
svg += ` data-vib3-geometry="${metadata.geometry}"`;
|
|
445
|
+
svg += ` data-vib3-system="${metadata.system}"`;
|
|
446
|
+
svg += ` data-vib3-core-type="${metadata.coreType}"`;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
svg += `>\n`;
|
|
450
|
+
|
|
451
|
+
// Defs section with CSS variables
|
|
452
|
+
svg += ` <defs>\n`;
|
|
453
|
+
svg += ` <style>\n`;
|
|
454
|
+
svg += ` :root {\n`;
|
|
455
|
+
svg += ` --vib3-hue: ${metadata.hue};\n`;
|
|
456
|
+
svg += ` --vib3-saturation: ${metadata.saturation};\n`;
|
|
457
|
+
svg += ` --vib3-intensity: ${metadata.intensity};\n`;
|
|
458
|
+
svg += ` }\n`;
|
|
459
|
+
svg += ` </style>\n`;
|
|
460
|
+
svg += ` </defs>\n`;
|
|
461
|
+
|
|
462
|
+
// Background
|
|
463
|
+
if (backgroundColor !== 'transparent') {
|
|
464
|
+
svg += ` <rect width="${width}" height="${height}" fill="${backgroundColor}"/>\n`;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Geometry layer
|
|
468
|
+
svg += ` <g id="geometry-layer">\n`;
|
|
469
|
+
|
|
470
|
+
// Render lines first (behind circles)
|
|
471
|
+
for (const path of paths) {
|
|
472
|
+
if (path.type === 'line') {
|
|
473
|
+
svg += ` <line x1="${path.x1}" y1="${path.y1}" x2="${path.x2}" y2="${path.y2}" `;
|
|
474
|
+
svg += `stroke="${path.stroke}" stroke-width="${path.strokeWidth}" stroke-linecap="round"/>\n`;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Render circles on top
|
|
479
|
+
for (const path of paths) {
|
|
480
|
+
if (path.type === 'circle') {
|
|
481
|
+
svg += ` <circle cx="${path.cx}" cy="${path.cy}" r="${path.r}" fill="${path.fill}"/>\n`;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
svg += ` </g>\n`;
|
|
486
|
+
|
|
487
|
+
// Watermark (Community tier)
|
|
488
|
+
if (includeWatermark) {
|
|
489
|
+
svg += ` <g id="vib3-watermark" opacity="0.3" transform="translate(10, ${height - 20})">\n`;
|
|
490
|
+
svg += ` <text font-size="10" fill="#666" font-family="sans-serif">${watermarkText}</text>\n`;
|
|
491
|
+
svg += ` </g>\n`;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
svg += `</svg>`;
|
|
495
|
+
|
|
496
|
+
return svg;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Export SVG to file (browser environment)
|
|
501
|
+
*/
|
|
502
|
+
export function downloadSVG(params, options = {}, filename = 'vib3-export.svg') {
|
|
503
|
+
const svg = exportSVG(params, options);
|
|
504
|
+
const blob = new Blob([svg], { type: 'image/svg+xml' });
|
|
505
|
+
const url = URL.createObjectURL(blob);
|
|
506
|
+
|
|
507
|
+
const link = document.createElement('a');
|
|
508
|
+
link.href = url;
|
|
509
|
+
link.download = filename;
|
|
510
|
+
link.click();
|
|
511
|
+
|
|
512
|
+
URL.revokeObjectURL(url);
|
|
513
|
+
return svg;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export default {
|
|
517
|
+
exportSVG,
|
|
518
|
+
downloadSVG
|
|
519
|
+
};
|