@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,540 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scene4D - Container for 4D scene management
|
|
3
|
+
*
|
|
4
|
+
* Provides a complete scene graph with:
|
|
5
|
+
* - Root node management
|
|
6
|
+
* - Node lookup by ID/name/tag
|
|
7
|
+
* - Layer-based filtering
|
|
8
|
+
* - Update and render traversal
|
|
9
|
+
* - Scene-wide settings
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { Node4D } from './Node4D.js';
|
|
13
|
+
import { Vec4 } from '../math/Vec4.js';
|
|
14
|
+
|
|
15
|
+
let sceneIdCounter = 0;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Scene4D class - Main scene container
|
|
19
|
+
*/
|
|
20
|
+
export class Scene4D {
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} [name] - Scene name
|
|
23
|
+
*/
|
|
24
|
+
constructor(name = '') {
|
|
25
|
+
/** @type {string} Unique scene ID */
|
|
26
|
+
this.id = `scene_${++sceneIdCounter}`;
|
|
27
|
+
|
|
28
|
+
/** @type {string} Scene name */
|
|
29
|
+
this.name = name || this.id;
|
|
30
|
+
|
|
31
|
+
/** @type {Node4D} Root node of scene graph */
|
|
32
|
+
this.root = new Node4D('__root__');
|
|
33
|
+
|
|
34
|
+
/** @type {Map<string, Node4D>} ID to node lookup */
|
|
35
|
+
this._nodeById = new Map();
|
|
36
|
+
this._nodeById.set(this.root.id, this.root);
|
|
37
|
+
|
|
38
|
+
/** @type {Set<Node4D>} Nodes pending addition */
|
|
39
|
+
this._pendingAdd = new Set();
|
|
40
|
+
|
|
41
|
+
/** @type {Set<Node4D>} Nodes pending removal */
|
|
42
|
+
this._pendingRemove = new Set();
|
|
43
|
+
|
|
44
|
+
/** @type {boolean} Whether scene is currently updating */
|
|
45
|
+
this._updating = false;
|
|
46
|
+
|
|
47
|
+
/** @type {Vec4} Scene background color (RGBA) */
|
|
48
|
+
this.backgroundColor = new Vec4(0, 0, 0, 1);
|
|
49
|
+
|
|
50
|
+
/** @type {Vec4} Ambient light color */
|
|
51
|
+
this.ambientLight = new Vec4(0.2, 0.2, 0.2, 1);
|
|
52
|
+
|
|
53
|
+
/** @type {number} 4D "fog" distance (W-axis fade) */
|
|
54
|
+
this.wFogDistance = 10;
|
|
55
|
+
|
|
56
|
+
/** @type {boolean} Whether W-fog is enabled */
|
|
57
|
+
this.wFogEnabled = false;
|
|
58
|
+
|
|
59
|
+
/** @type {object} Scene metadata */
|
|
60
|
+
this.metadata = {};
|
|
61
|
+
|
|
62
|
+
/** @type {function[]} Update callbacks */
|
|
63
|
+
this._updateCallbacks = [];
|
|
64
|
+
|
|
65
|
+
/** @type {number} Total nodes in scene (cached) */
|
|
66
|
+
this._nodeCount = 1; // Root counts as 1
|
|
67
|
+
|
|
68
|
+
/** @type {boolean} Whether node count needs recalculation */
|
|
69
|
+
this._nodeCountDirty = false;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ==================== Node Management ====================
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Add a node to the scene (under root)
|
|
76
|
+
* @param {Node4D} node
|
|
77
|
+
* @returns {this}
|
|
78
|
+
*/
|
|
79
|
+
add(node) {
|
|
80
|
+
if (this._updating) {
|
|
81
|
+
this._pendingAdd.add(node);
|
|
82
|
+
return this;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this._addNodeImmediate(node);
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Add node immediately
|
|
91
|
+
* @private
|
|
92
|
+
*/
|
|
93
|
+
_addNodeImmediate(node) {
|
|
94
|
+
if (node.parent === this.root) return;
|
|
95
|
+
|
|
96
|
+
this.root.addChild(node);
|
|
97
|
+
this._registerNode(node);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Remove a node from the scene
|
|
102
|
+
* @param {Node4D} node
|
|
103
|
+
* @returns {boolean}
|
|
104
|
+
*/
|
|
105
|
+
remove(node) {
|
|
106
|
+
if (node === this.root) return false;
|
|
107
|
+
|
|
108
|
+
if (this._updating) {
|
|
109
|
+
this._pendingRemove.add(node);
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return this._removeNodeImmediate(node);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Remove node immediately
|
|
118
|
+
* @private
|
|
119
|
+
*/
|
|
120
|
+
_removeNodeImmediate(node) {
|
|
121
|
+
this._unregisterNode(node);
|
|
122
|
+
node.parent = null;
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Register node and all descendants in lookup
|
|
128
|
+
* @private
|
|
129
|
+
*/
|
|
130
|
+
_registerNode(node) {
|
|
131
|
+
node.traverse(n => {
|
|
132
|
+
this._nodeById.set(n.id, n);
|
|
133
|
+
});
|
|
134
|
+
this._nodeCountDirty = true;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Unregister node and all descendants from lookup
|
|
139
|
+
* @private
|
|
140
|
+
*/
|
|
141
|
+
_unregisterNode(node) {
|
|
142
|
+
node.traverse(n => {
|
|
143
|
+
this._nodeById.delete(n.id);
|
|
144
|
+
});
|
|
145
|
+
this._nodeCountDirty = true;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Process pending additions and removals
|
|
150
|
+
* @private
|
|
151
|
+
*/
|
|
152
|
+
_processPending() {
|
|
153
|
+
for (const node of this._pendingRemove) {
|
|
154
|
+
this._removeNodeImmediate(node);
|
|
155
|
+
}
|
|
156
|
+
this._pendingRemove.clear();
|
|
157
|
+
|
|
158
|
+
for (const node of this._pendingAdd) {
|
|
159
|
+
this._addNodeImmediate(node);
|
|
160
|
+
}
|
|
161
|
+
this._pendingAdd.clear();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get node by ID
|
|
166
|
+
* @param {string} id
|
|
167
|
+
* @returns {Node4D|undefined}
|
|
168
|
+
*/
|
|
169
|
+
getNodeById(id) {
|
|
170
|
+
return this._nodeById.get(id);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get node by name (first match)
|
|
175
|
+
* @param {string} name
|
|
176
|
+
* @returns {Node4D|undefined}
|
|
177
|
+
*/
|
|
178
|
+
getNodeByName(name) {
|
|
179
|
+
return this.root.findByName(name);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Get all nodes with tag
|
|
184
|
+
* @param {string} tag
|
|
185
|
+
* @returns {Node4D[]}
|
|
186
|
+
*/
|
|
187
|
+
getNodesByTag(tag) {
|
|
188
|
+
return this.root.findByTag(tag);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get all nodes on a layer
|
|
193
|
+
* @param {number} layer - Layer bit (0-31)
|
|
194
|
+
* @returns {Node4D[]}
|
|
195
|
+
*/
|
|
196
|
+
getNodesByLayer(layer) {
|
|
197
|
+
const mask = 1 << layer;
|
|
198
|
+
const results = [];
|
|
199
|
+
this.root.traverse(node => {
|
|
200
|
+
if (node.layerMask & mask) {
|
|
201
|
+
results.push(node);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
return results;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Get total node count
|
|
209
|
+
* @returns {number}
|
|
210
|
+
*/
|
|
211
|
+
get nodeCount() {
|
|
212
|
+
if (this._nodeCountDirty) {
|
|
213
|
+
this._nodeCount = this._nodeById.size;
|
|
214
|
+
this._nodeCountDirty = false;
|
|
215
|
+
}
|
|
216
|
+
return this._nodeCount;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Check if scene contains a node
|
|
221
|
+
* @param {Node4D} node
|
|
222
|
+
* @returns {boolean}
|
|
223
|
+
*/
|
|
224
|
+
contains(node) {
|
|
225
|
+
return this._nodeById.has(node.id);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ==================== Traversal ====================
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Traverse all nodes depth-first
|
|
232
|
+
* @param {function(Node4D): boolean|void} callback
|
|
233
|
+
*/
|
|
234
|
+
traverse(callback) {
|
|
235
|
+
this.root.traverse(callback);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Traverse only visible nodes
|
|
240
|
+
* @param {function(Node4D): void} callback
|
|
241
|
+
*/
|
|
242
|
+
traverseVisible(callback) {
|
|
243
|
+
this.root.traverseVisible(callback);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Traverse nodes matching layer mask
|
|
248
|
+
* @param {number} mask
|
|
249
|
+
* @param {function(Node4D): void} callback
|
|
250
|
+
*/
|
|
251
|
+
traverseByLayer(mask, callback) {
|
|
252
|
+
this.root.traverse(node => {
|
|
253
|
+
if (node.layerMask & mask) {
|
|
254
|
+
callback(node);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Get all visible nodes sorted by W coordinate (far to near)
|
|
261
|
+
* @returns {Node4D[]}
|
|
262
|
+
*/
|
|
263
|
+
getVisibleNodesSortedByW() {
|
|
264
|
+
const nodes = [];
|
|
265
|
+
this.traverseVisible(node => {
|
|
266
|
+
if (node !== this.root) {
|
|
267
|
+
nodes.push(node);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Sort by world W coordinate (far to near for proper transparency)
|
|
272
|
+
nodes.sort((a, b) => a.worldPosition.w - b.worldPosition.w);
|
|
273
|
+
return nodes;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ==================== Update Loop ====================
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Register an update callback
|
|
280
|
+
* @param {function(number): void} callback - Called with deltaTime
|
|
281
|
+
* @returns {function} Unsubscribe function
|
|
282
|
+
*/
|
|
283
|
+
onUpdate(callback) {
|
|
284
|
+
this._updateCallbacks.push(callback);
|
|
285
|
+
return () => {
|
|
286
|
+
const idx = this._updateCallbacks.indexOf(callback);
|
|
287
|
+
if (idx !== -1) {
|
|
288
|
+
this._updateCallbacks.splice(idx, 1);
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Update the scene
|
|
295
|
+
* @param {number} deltaTime - Time since last update in seconds
|
|
296
|
+
*/
|
|
297
|
+
update(deltaTime) {
|
|
298
|
+
this._updating = true;
|
|
299
|
+
|
|
300
|
+
// Call update callbacks
|
|
301
|
+
for (const callback of this._updateCallbacks) {
|
|
302
|
+
callback(deltaTime);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Update all node transforms (ensures world matrices are current)
|
|
306
|
+
this.root.traverse(node => {
|
|
307
|
+
// Access worldMatrix to trigger update if dirty
|
|
308
|
+
void node.worldMatrix;
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
this._updating = false;
|
|
312
|
+
|
|
313
|
+
// Process pending operations
|
|
314
|
+
this._processPending();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// ==================== Queries ====================
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Find nodes within a 4D sphere
|
|
321
|
+
* @param {Vec4} center
|
|
322
|
+
* @param {number} radius
|
|
323
|
+
* @returns {Node4D[]}
|
|
324
|
+
*/
|
|
325
|
+
findNodesInSphere(center, radius) {
|
|
326
|
+
const results = [];
|
|
327
|
+
const radiusSq = radius * radius;
|
|
328
|
+
|
|
329
|
+
this.root.traverse(node => {
|
|
330
|
+
if (node === this.root) return;
|
|
331
|
+
const dist = node.worldPosition.sub(center).lengthSquared();
|
|
332
|
+
if (dist <= radiusSq) {
|
|
333
|
+
results.push(node);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
return results;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Find nodes within a 4D box
|
|
342
|
+
* @param {Vec4} min
|
|
343
|
+
* @param {Vec4} max
|
|
344
|
+
* @returns {Node4D[]}
|
|
345
|
+
*/
|
|
346
|
+
findNodesInBox(min, max) {
|
|
347
|
+
const results = [];
|
|
348
|
+
|
|
349
|
+
this.root.traverse(node => {
|
|
350
|
+
if (node === this.root) return;
|
|
351
|
+
const pos = node.worldPosition;
|
|
352
|
+
if (pos.x >= min.x && pos.x <= max.x &&
|
|
353
|
+
pos.y >= min.y && pos.y <= max.y &&
|
|
354
|
+
pos.z >= min.z && pos.z <= max.z &&
|
|
355
|
+
pos.w >= min.w && pos.w <= max.w) {
|
|
356
|
+
results.push(node);
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
return results;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Find nearest node to a point
|
|
365
|
+
* @param {Vec4} point
|
|
366
|
+
* @param {number} [maxDistance] - Maximum search distance
|
|
367
|
+
* @returns {Node4D|null}
|
|
368
|
+
*/
|
|
369
|
+
findNearestNode(point, maxDistance = Infinity) {
|
|
370
|
+
let nearest = null;
|
|
371
|
+
let nearestDistSq = maxDistance * maxDistance;
|
|
372
|
+
|
|
373
|
+
this.root.traverse(node => {
|
|
374
|
+
if (node === this.root) return;
|
|
375
|
+
const distSq = node.worldPosition.sub(point).lengthSquared();
|
|
376
|
+
if (distSq < nearestDistSq) {
|
|
377
|
+
nearestDistSq = distSq;
|
|
378
|
+
nearest = node;
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
return nearest;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Raycast into the scene (simplified 4D ray)
|
|
387
|
+
* @param {Vec4} origin
|
|
388
|
+
* @param {Vec4} direction
|
|
389
|
+
* @param {number} [maxDistance]
|
|
390
|
+
* @returns {Array<{node: Node4D, distance: number}>}
|
|
391
|
+
*/
|
|
392
|
+
raycast(origin, direction, maxDistance = 1000) {
|
|
393
|
+
const hits = [];
|
|
394
|
+
const dir = direction.normalize();
|
|
395
|
+
|
|
396
|
+
this.root.traverse(node => {
|
|
397
|
+
if (node === this.root) return;
|
|
398
|
+
|
|
399
|
+
// Simplified: treat each node as a point
|
|
400
|
+
const toNode = node.worldPosition.sub(origin);
|
|
401
|
+
const dist = toNode.dot(dir);
|
|
402
|
+
|
|
403
|
+
if (dist > 0 && dist < maxDistance) {
|
|
404
|
+
// Check perpendicular distance
|
|
405
|
+
const closest = origin.add(dir.scale(dist));
|
|
406
|
+
const perpDist = node.worldPosition.sub(closest).length();
|
|
407
|
+
|
|
408
|
+
// Assume nodes have radius 0.5 for hit detection
|
|
409
|
+
if (perpDist < 0.5) {
|
|
410
|
+
hits.push({ node, distance: dist });
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// Sort by distance
|
|
416
|
+
hits.sort((a, b) => a.distance - b.distance);
|
|
417
|
+
return hits;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// ==================== Lifecycle ====================
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Clear all nodes from scene
|
|
424
|
+
*/
|
|
425
|
+
clear() {
|
|
426
|
+
this.root.removeAllChildren();
|
|
427
|
+
this._nodeById.clear();
|
|
428
|
+
this._nodeById.set(this.root.id, this.root);
|
|
429
|
+
this._pendingAdd.clear();
|
|
430
|
+
this._pendingRemove.clear();
|
|
431
|
+
this._nodeCountDirty = true;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Dispose scene and all nodes
|
|
436
|
+
*/
|
|
437
|
+
dispose() {
|
|
438
|
+
this.clear();
|
|
439
|
+
this._updateCallbacks = [];
|
|
440
|
+
this.root.dispose();
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Clone scene with all nodes
|
|
445
|
+
* @returns {Scene4D}
|
|
446
|
+
*/
|
|
447
|
+
clone() {
|
|
448
|
+
const cloned = new Scene4D(this.name + '_clone');
|
|
449
|
+
cloned.backgroundColor = this.backgroundColor.clone();
|
|
450
|
+
cloned.ambientLight = this.ambientLight.clone();
|
|
451
|
+
cloned.wFogDistance = this.wFogDistance;
|
|
452
|
+
cloned.wFogEnabled = this.wFogEnabled;
|
|
453
|
+
cloned.metadata = { ...this.metadata };
|
|
454
|
+
|
|
455
|
+
// Clone all children of root
|
|
456
|
+
for (const child of this.root.children) {
|
|
457
|
+
cloned.add(child.cloneDeep());
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return cloned;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ==================== Serialization ====================
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Serialize scene to JSON
|
|
467
|
+
* @returns {object}
|
|
468
|
+
*/
|
|
469
|
+
toJSON() {
|
|
470
|
+
return {
|
|
471
|
+
id: this.id,
|
|
472
|
+
name: this.name,
|
|
473
|
+
backgroundColor: [
|
|
474
|
+
this.backgroundColor.x,
|
|
475
|
+
this.backgroundColor.y,
|
|
476
|
+
this.backgroundColor.z,
|
|
477
|
+
this.backgroundColor.w
|
|
478
|
+
],
|
|
479
|
+
ambientLight: [
|
|
480
|
+
this.ambientLight.x,
|
|
481
|
+
this.ambientLight.y,
|
|
482
|
+
this.ambientLight.z,
|
|
483
|
+
this.ambientLight.w
|
|
484
|
+
],
|
|
485
|
+
wFogDistance: this.wFogDistance,
|
|
486
|
+
wFogEnabled: this.wFogEnabled,
|
|
487
|
+
metadata: this.metadata,
|
|
488
|
+
nodes: this.root.children.map(c => c.toJSON())
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Create scene from JSON
|
|
494
|
+
* @param {object} json
|
|
495
|
+
* @returns {Scene4D}
|
|
496
|
+
*/
|
|
497
|
+
static fromJSON(json) {
|
|
498
|
+
const scene = new Scene4D(json.name);
|
|
499
|
+
scene.backgroundColor = new Vec4(...json.backgroundColor);
|
|
500
|
+
scene.ambientLight = new Vec4(...json.ambientLight);
|
|
501
|
+
scene.wFogDistance = json.wFogDistance;
|
|
502
|
+
scene.wFogEnabled = json.wFogEnabled;
|
|
503
|
+
scene.metadata = json.metadata || {};
|
|
504
|
+
|
|
505
|
+
for (const nodeJson of (json.nodes || [])) {
|
|
506
|
+
scene.add(Node4D.fromJSON(nodeJson));
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return scene;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// ==================== Statistics ====================
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Get scene statistics
|
|
516
|
+
* @returns {object}
|
|
517
|
+
*/
|
|
518
|
+
getStats() {
|
|
519
|
+
let visibleCount = 0;
|
|
520
|
+
let enabledCount = 0;
|
|
521
|
+
let maxDepth = 0;
|
|
522
|
+
|
|
523
|
+
this.root.traverse(node => {
|
|
524
|
+
if (node.visible) visibleCount++;
|
|
525
|
+
if (node.enabled) enabledCount++;
|
|
526
|
+
maxDepth = Math.max(maxDepth, node.getDepth());
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
return {
|
|
530
|
+
totalNodes: this.nodeCount,
|
|
531
|
+
visibleNodes: visibleCount,
|
|
532
|
+
enabledNodes: enabledCount,
|
|
533
|
+
maxDepth,
|
|
534
|
+
pendingAdd: this._pendingAdd.size,
|
|
535
|
+
pendingRemove: this._pendingRemove.size
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
export default Scene4D;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scene Module
|
|
3
|
+
*
|
|
4
|
+
* Complete 4D scene graph system with resource management.
|
|
5
|
+
*
|
|
6
|
+
* Core Classes:
|
|
7
|
+
* - Node4D: Transform hierarchy node
|
|
8
|
+
* - Scene4D: Scene container
|
|
9
|
+
* - ResourceManager: Reference-counted resources
|
|
10
|
+
* - MemoryPool: Object pooling
|
|
11
|
+
* - Disposable: Cascade disposal
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Scene Graph
|
|
15
|
+
export { Node4D, default as Node4DDefault } from './Node4D.js';
|
|
16
|
+
export { Scene4D, default as Scene4DDefault } from './Scene4D.js';
|
|
17
|
+
|
|
18
|
+
// Resource Management
|
|
19
|
+
export {
|
|
20
|
+
ResourceManager,
|
|
21
|
+
ManagedResource,
|
|
22
|
+
ResourceTypes,
|
|
23
|
+
default as ResourceManagerDefault
|
|
24
|
+
} from './ResourceManager.js';
|
|
25
|
+
|
|
26
|
+
// Memory Pools
|
|
27
|
+
export {
|
|
28
|
+
ObjectPool,
|
|
29
|
+
TypedArrayPool,
|
|
30
|
+
Vec4Pool,
|
|
31
|
+
Mat4x4Pool,
|
|
32
|
+
PoolManager,
|
|
33
|
+
pools,
|
|
34
|
+
default as PoolManagerDefault
|
|
35
|
+
} from './MemoryPool.js';
|
|
36
|
+
|
|
37
|
+
// Disposal System
|
|
38
|
+
export {
|
|
39
|
+
Disposable,
|
|
40
|
+
DisposalManager,
|
|
41
|
+
DisposalState,
|
|
42
|
+
CompositeDisposable,
|
|
43
|
+
SingleAssignmentDisposable,
|
|
44
|
+
SerialDisposable,
|
|
45
|
+
CallbackDisposable,
|
|
46
|
+
createDisposable,
|
|
47
|
+
disposalManager,
|
|
48
|
+
default as DisposableDefault
|
|
49
|
+
} from './Disposable.js';
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Create a complete scene setup with all managers
|
|
53
|
+
* @param {object} [options]
|
|
54
|
+
* @returns {object}
|
|
55
|
+
*/
|
|
56
|
+
export function createSceneContext(options = {}) {
|
|
57
|
+
const {
|
|
58
|
+
sceneName = 'main',
|
|
59
|
+
memoryLimit = 256 * 1024 * 1024, // 256MB default
|
|
60
|
+
poolInitialSize = 100
|
|
61
|
+
} = options;
|
|
62
|
+
|
|
63
|
+
const scene = new (require('./Scene4D.js').Scene4D)(sceneName);
|
|
64
|
+
const resources = new (require('./ResourceManager.js').ResourceManager)();
|
|
65
|
+
const disposal = new (require('./Disposable.js').DisposalManager)();
|
|
66
|
+
const poolManager = new (require('./MemoryPool.js').PoolManager)();
|
|
67
|
+
|
|
68
|
+
resources.memoryLimit = memoryLimit;
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
scene,
|
|
72
|
+
resources,
|
|
73
|
+
disposal,
|
|
74
|
+
pools: poolManager,
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Dispose all context resources
|
|
78
|
+
*/
|
|
79
|
+
dispose() {
|
|
80
|
+
disposal.disposeAll();
|
|
81
|
+
resources.disposeAll();
|
|
82
|
+
scene.dispose();
|
|
83
|
+
poolManager.clearAll();
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get combined statistics
|
|
88
|
+
*/
|
|
89
|
+
getStats() {
|
|
90
|
+
return {
|
|
91
|
+
scene: scene.getStats(),
|
|
92
|
+
resources: resources.getStats(),
|
|
93
|
+
disposal: disposal.getStats(),
|
|
94
|
+
pools: poolManager.getStats()
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "error.schema.json",
|
|
4
|
+
"title": "VIB3+ Error Schema",
|
|
5
|
+
"description": "Actionable error format for agentic API consumption",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"error": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
"type": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"enum": [
|
|
14
|
+
"ValidationError",
|
|
15
|
+
"RenderError",
|
|
16
|
+
"ResourceError",
|
|
17
|
+
"SystemError",
|
|
18
|
+
"ConfigurationError",
|
|
19
|
+
"NotFoundError",
|
|
20
|
+
"PermissionError"
|
|
21
|
+
],
|
|
22
|
+
"description": "Error category"
|
|
23
|
+
},
|
|
24
|
+
"code": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"pattern": "^[A-Z_]+$",
|
|
27
|
+
"description": "Machine-readable error code",
|
|
28
|
+
"examples": [
|
|
29
|
+
"INVALID_GEOMETRY_INDEX",
|
|
30
|
+
"INVALID_ROTATION_PLANE",
|
|
31
|
+
"WEBGL_CONTEXT_LOST",
|
|
32
|
+
"SYSTEM_NOT_INITIALIZED",
|
|
33
|
+
"PARAMETER_OUT_OF_RANGE"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"message": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "Human-readable error description"
|
|
39
|
+
},
|
|
40
|
+
"parameter": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "The parameter that caused the error, if applicable"
|
|
43
|
+
},
|
|
44
|
+
"provided_value": {
|
|
45
|
+
"description": "The invalid value that was provided"
|
|
46
|
+
},
|
|
47
|
+
"valid_options": {
|
|
48
|
+
"type": "array",
|
|
49
|
+
"description": "List of valid options for enum-type errors"
|
|
50
|
+
},
|
|
51
|
+
"valid_range": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"properties": {
|
|
54
|
+
"min": { "type": "number" },
|
|
55
|
+
"max": { "type": "number" }
|
|
56
|
+
},
|
|
57
|
+
"description": "Valid range for numeric errors"
|
|
58
|
+
},
|
|
59
|
+
"suggestion": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"description": "Actionable suggestion for the agent to fix the error"
|
|
62
|
+
},
|
|
63
|
+
"documentation_url": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"format": "uri",
|
|
66
|
+
"description": "Link to relevant documentation"
|
|
67
|
+
},
|
|
68
|
+
"retry_possible": {
|
|
69
|
+
"type": "boolean",
|
|
70
|
+
"description": "Whether retrying the operation might succeed",
|
|
71
|
+
"default": false
|
|
72
|
+
},
|
|
73
|
+
"retry_after_ms": {
|
|
74
|
+
"type": "integer",
|
|
75
|
+
"description": "Suggested wait time before retry, in milliseconds"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"required": ["type", "code", "message"],
|
|
79
|
+
"additionalProperties": false
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"required": ["error"],
|
|
83
|
+
"additionalProperties": false
|
|
84
|
+
}
|