@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.
Files changed (258) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
  3. package/DOCS/CI_TESTING.md +38 -0
  4. package/DOCS/CLI_ONBOARDING.md +75 -0
  5. package/DOCS/CONTROL_REFERENCE.md +64 -0
  6. package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
  7. package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
  8. package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
  9. package/DOCS/ENV_SETUP.md +189 -0
  10. package/DOCS/EXPORT_FORMATS.md +417 -0
  11. package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
  12. package/DOCS/LICENSING_TIERS.md +275 -0
  13. package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
  14. package/DOCS/OBS_SETUP_GUIDE.md +98 -0
  15. package/DOCS/PROJECT_SETUP.md +66 -0
  16. package/DOCS/RENDERER_LIFECYCLE.md +40 -0
  17. package/DOCS/REPO_MANIFEST.md +121 -0
  18. package/DOCS/SESSION_014_PLAN.md +195 -0
  19. package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
  20. package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
  21. package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
  22. package/DOCS/SYSTEM_INVENTORY.md +520 -0
  23. package/DOCS/TELEMETRY_EXPORTS.md +34 -0
  24. package/DOCS/WEBGPU_STATUS.md +38 -0
  25. package/DOCS/XR_BENCHMARKS.md +608 -0
  26. package/LICENSE +21 -0
  27. package/README.md +426 -0
  28. package/docs/.nojekyll +0 -0
  29. package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
  30. package/docs/02-hyperspatial_ego_death.html +346 -0
  31. package/docs/03-post_cartesian_sublime.html +346 -0
  32. package/docs/04-crystalline_void_meditation.html +346 -0
  33. package/docs/05-quantum_decoherence_ballet.html +346 -0
  34. package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
  35. package/docs/07-hyperspatial_ego_death.html +346 -0
  36. package/docs/08-post_cartesian_sublime.html +346 -0
  37. package/docs/09-crystalline_void_meditation.html +346 -0
  38. package/docs/10-quantum_decoherence_ballet.html +346 -0
  39. package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
  40. package/docs/12-hyperspatial_ego_death.html +346 -0
  41. package/docs/13-post_cartesian_sublime.html +346 -0
  42. package/docs/index.html +794 -0
  43. package/docs/test-hub.html +441 -0
  44. package/docs/url-state.js +102 -0
  45. package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
  46. package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
  47. package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
  48. package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
  49. package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
  50. package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
  51. package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
  52. package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
  53. package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
  54. package/docs/vib3-exports/index.html +238 -0
  55. package/docs/webgpu-live.html +702 -0
  56. package/package.json +367 -0
  57. package/src/advanced/AIPresetGenerator.js +777 -0
  58. package/src/advanced/MIDIController.js +703 -0
  59. package/src/advanced/OffscreenWorker.js +1051 -0
  60. package/src/advanced/WebGPUCompute.js +1051 -0
  61. package/src/advanced/WebXRRenderer.js +680 -0
  62. package/src/agent/cli/AgentCLI.js +615 -0
  63. package/src/agent/cli/index.js +14 -0
  64. package/src/agent/index.js +73 -0
  65. package/src/agent/mcp/MCPServer.js +950 -0
  66. package/src/agent/mcp/index.js +9 -0
  67. package/src/agent/mcp/tools.js +548 -0
  68. package/src/agent/telemetry/EventStream.js +669 -0
  69. package/src/agent/telemetry/Instrumentation.js +618 -0
  70. package/src/agent/telemetry/TelemetryExporters.js +427 -0
  71. package/src/agent/telemetry/TelemetryService.js +464 -0
  72. package/src/agent/telemetry/index.js +52 -0
  73. package/src/benchmarks/BenchmarkRunner.js +381 -0
  74. package/src/benchmarks/MetricsCollector.js +299 -0
  75. package/src/benchmarks/index.js +9 -0
  76. package/src/benchmarks/scenes.js +259 -0
  77. package/src/cli/index.js +675 -0
  78. package/src/config/ApiConfig.js +88 -0
  79. package/src/core/CanvasManager.js +217 -0
  80. package/src/core/ErrorReporter.js +117 -0
  81. package/src/core/ParameterMapper.js +333 -0
  82. package/src/core/Parameters.js +396 -0
  83. package/src/core/RendererContracts.js +200 -0
  84. package/src/core/UnifiedResourceManager.js +370 -0
  85. package/src/core/VIB3Engine.js +636 -0
  86. package/src/core/renderers/FacetedRendererAdapter.js +32 -0
  87. package/src/core/renderers/HolographicRendererAdapter.js +29 -0
  88. package/src/core/renderers/QuantumRendererAdapter.js +29 -0
  89. package/src/core/renderers/RendererLifecycleManager.js +63 -0
  90. package/src/creative/ColorPresetsSystem.js +980 -0
  91. package/src/creative/ParameterTimeline.js +1061 -0
  92. package/src/creative/PostProcessingPipeline.js +1113 -0
  93. package/src/creative/TransitionAnimator.js +683 -0
  94. package/src/export/CSSExporter.js +226 -0
  95. package/src/export/CardGeneratorBase.js +279 -0
  96. package/src/export/ExportManager.js +580 -0
  97. package/src/export/FacetedCardGenerator.js +279 -0
  98. package/src/export/HolographicCardGenerator.js +543 -0
  99. package/src/export/LottieExporter.js +552 -0
  100. package/src/export/QuantumCardGenerator.js +315 -0
  101. package/src/export/SVGExporter.js +519 -0
  102. package/src/export/ShaderExporter.js +903 -0
  103. package/src/export/TradingCardGenerator.js +3055 -0
  104. package/src/export/TradingCardManager.js +181 -0
  105. package/src/export/VIB3PackageExporter.js +559 -0
  106. package/src/export/index.js +14 -0
  107. package/src/export/systems/TradingCardSystemFaceted.js +494 -0
  108. package/src/export/systems/TradingCardSystemHolographic.js +452 -0
  109. package/src/export/systems/TradingCardSystemQuantum.js +411 -0
  110. package/src/faceted/FacetedSystem.js +963 -0
  111. package/src/features/CollectionManager.js +433 -0
  112. package/src/gallery/CollectionManager.js +240 -0
  113. package/src/gallery/GallerySystem.js +485 -0
  114. package/src/geometry/GeometryFactory.js +314 -0
  115. package/src/geometry/GeometryLibrary.js +72 -0
  116. package/src/geometry/buffers/BufferBuilder.js +338 -0
  117. package/src/geometry/buffers/index.js +18 -0
  118. package/src/geometry/generators/Crystal.js +420 -0
  119. package/src/geometry/generators/Fractal.js +298 -0
  120. package/src/geometry/generators/KleinBottle.js +197 -0
  121. package/src/geometry/generators/Sphere.js +192 -0
  122. package/src/geometry/generators/Tesseract.js +160 -0
  123. package/src/geometry/generators/Tetrahedron.js +225 -0
  124. package/src/geometry/generators/Torus.js +304 -0
  125. package/src/geometry/generators/Wave.js +341 -0
  126. package/src/geometry/index.js +142 -0
  127. package/src/geometry/warp/HypersphereCore.js +211 -0
  128. package/src/geometry/warp/HypertetraCore.js +386 -0
  129. package/src/geometry/warp/index.js +57 -0
  130. package/src/holograms/HolographicVisualizer.js +1073 -0
  131. package/src/holograms/RealHolographicSystem.js +966 -0
  132. package/src/holograms/variantRegistry.js +69 -0
  133. package/src/integrations/FigmaPlugin.js +854 -0
  134. package/src/integrations/OBSMode.js +754 -0
  135. package/src/integrations/ThreeJsPackage.js +660 -0
  136. package/src/integrations/TouchDesignerExport.js +552 -0
  137. package/src/integrations/frameworks/Vib3React.js +591 -0
  138. package/src/integrations/frameworks/Vib3Svelte.js +654 -0
  139. package/src/integrations/frameworks/Vib3Vue.js +628 -0
  140. package/src/llm/LLMParameterInterface.js +240 -0
  141. package/src/llm/LLMParameterUI.js +577 -0
  142. package/src/math/Mat4x4.js +708 -0
  143. package/src/math/Projection.js +341 -0
  144. package/src/math/Rotor4D.js +637 -0
  145. package/src/math/Vec4.js +476 -0
  146. package/src/math/constants.js +164 -0
  147. package/src/math/index.js +68 -0
  148. package/src/math/projections.js +54 -0
  149. package/src/math/rotations.js +196 -0
  150. package/src/quantum/QuantumEngine.js +906 -0
  151. package/src/quantum/QuantumVisualizer.js +1103 -0
  152. package/src/reactivity/ReactivityConfig.js +499 -0
  153. package/src/reactivity/ReactivityManager.js +586 -0
  154. package/src/reactivity/SpatialInputSystem.js +1783 -0
  155. package/src/reactivity/index.js +93 -0
  156. package/src/render/CommandBuffer.js +465 -0
  157. package/src/render/MultiCanvasBridge.js +340 -0
  158. package/src/render/RenderCommand.js +514 -0
  159. package/src/render/RenderResourceRegistry.js +523 -0
  160. package/src/render/RenderState.js +552 -0
  161. package/src/render/RenderTarget.js +512 -0
  162. package/src/render/ShaderLoader.js +253 -0
  163. package/src/render/ShaderProgram.js +599 -0
  164. package/src/render/UnifiedRenderBridge.js +496 -0
  165. package/src/render/backends/WebGLBackend.js +1108 -0
  166. package/src/render/backends/WebGPUBackend.js +1409 -0
  167. package/src/render/commands/CommandBufferExecutor.js +607 -0
  168. package/src/render/commands/RenderCommandBuffer.js +661 -0
  169. package/src/render/commands/index.js +17 -0
  170. package/src/render/index.js +367 -0
  171. package/src/scene/Disposable.js +498 -0
  172. package/src/scene/MemoryPool.js +618 -0
  173. package/src/scene/Node4D.js +697 -0
  174. package/src/scene/ResourceManager.js +599 -0
  175. package/src/scene/Scene4D.js +540 -0
  176. package/src/scene/index.js +98 -0
  177. package/src/schemas/error.schema.json +84 -0
  178. package/src/schemas/extension.schema.json +88 -0
  179. package/src/schemas/index.js +214 -0
  180. package/src/schemas/parameters.schema.json +142 -0
  181. package/src/schemas/tool-pack.schema.json +44 -0
  182. package/src/schemas/tool-response.schema.json +127 -0
  183. package/src/shaders/common/fullscreen.vert.glsl +5 -0
  184. package/src/shaders/common/fullscreen.vert.wgsl +17 -0
  185. package/src/shaders/common/geometry24.glsl +65 -0
  186. package/src/shaders/common/geometry24.wgsl +54 -0
  187. package/src/shaders/common/rotation4d.glsl +85 -0
  188. package/src/shaders/common/rotation4d.wgsl +86 -0
  189. package/src/shaders/common/uniforms.glsl +44 -0
  190. package/src/shaders/common/uniforms.wgsl +48 -0
  191. package/src/shaders/faceted/faceted.frag.glsl +129 -0
  192. package/src/shaders/faceted/faceted.frag.wgsl +164 -0
  193. package/src/shaders/holographic/holographic.frag.glsl +406 -0
  194. package/src/shaders/holographic/holographic.frag.wgsl +185 -0
  195. package/src/shaders/quantum/quantum.frag.glsl +513 -0
  196. package/src/shaders/quantum/quantum.frag.wgsl +361 -0
  197. package/src/testing/ParallelTestFramework.js +519 -0
  198. package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
  199. package/src/testing/exportFormats.test.js +8 -0
  200. package/src/testing/projections.test.js +14 -0
  201. package/src/testing/rotations.test.js +37 -0
  202. package/src/ui/InteractivityMenu.js +516 -0
  203. package/src/ui/StatusManager.js +96 -0
  204. package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
  205. package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
  206. package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
  207. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
  208. package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
  209. package/src/variations/VariationManager.js +431 -0
  210. package/src/viewer/AudioReactivity.js +505 -0
  211. package/src/viewer/CardBending.js +481 -0
  212. package/src/viewer/GalleryUI.js +832 -0
  213. package/src/viewer/ReactivityManager.js +590 -0
  214. package/src/viewer/TradingCardExporter.js +600 -0
  215. package/src/viewer/ViewerPortal.js +374 -0
  216. package/src/viewer/index.js +12 -0
  217. package/src/wasm/WasmLoader.js +296 -0
  218. package/src/wasm/index.js +132 -0
  219. package/tools/agentic/mcpTools.js +88 -0
  220. package/tools/cli/agent-cli.js +92 -0
  221. package/tools/export/formats.js +24 -0
  222. package/tools/math/rotation-baseline.mjs +64 -0
  223. package/tools/shader-sync-verify.js +937 -0
  224. package/tools/telemetry/manifestPipeline.js +141 -0
  225. package/tools/telemetry/telemetryEvents.js +35 -0
  226. package/types/adaptive-sdk.d.ts +185 -0
  227. package/types/advanced/AIPresetGenerator.d.ts +81 -0
  228. package/types/advanced/MIDIController.d.ts +100 -0
  229. package/types/advanced/OffscreenWorker.d.ts +82 -0
  230. package/types/advanced/WebGPUCompute.d.ts +52 -0
  231. package/types/advanced/WebXRRenderer.d.ts +77 -0
  232. package/types/advanced/index.d.ts +46 -0
  233. package/types/core/ErrorReporter.d.ts +50 -0
  234. package/types/core/VIB3Engine.d.ts +204 -0
  235. package/types/creative/ColorPresetsSystem.d.ts +91 -0
  236. package/types/creative/ParameterTimeline.d.ts +74 -0
  237. package/types/creative/PostProcessingPipeline.d.ts +109 -0
  238. package/types/creative/TransitionAnimator.d.ts +71 -0
  239. package/types/creative/index.d.ts +35 -0
  240. package/types/integrations/FigmaPlugin.d.ts +46 -0
  241. package/types/integrations/OBSMode.d.ts +74 -0
  242. package/types/integrations/ThreeJsPackage.d.ts +62 -0
  243. package/types/integrations/TouchDesignerExport.d.ts +36 -0
  244. package/types/integrations/Vib3React.d.ts +74 -0
  245. package/types/integrations/Vib3Svelte.d.ts +63 -0
  246. package/types/integrations/Vib3Vue.d.ts +55 -0
  247. package/types/integrations/index.d.ts +52 -0
  248. package/types/reactivity/SpatialInputSystem.d.ts +173 -0
  249. package/types/reactivity/index.d.ts +394 -0
  250. package/types/render/CommandBuffer.d.ts +169 -0
  251. package/types/render/RenderCommand.d.ts +312 -0
  252. package/types/render/RenderState.d.ts +279 -0
  253. package/types/render/RenderTarget.d.ts +254 -0
  254. package/types/render/ShaderProgram.d.ts +277 -0
  255. package/types/render/UnifiedRenderBridge.d.ts +143 -0
  256. package/types/render/WebGLBackend.d.ts +168 -0
  257. package/types/render/WebGPUBackend.d.ts +186 -0
  258. package/types/render/index.d.ts +141 -0
@@ -0,0 +1,697 @@
1
+ /**
2
+ * Node4D - Base class for 4D scene graph nodes
3
+ *
4
+ * Provides hierarchical transform management with parent-child relationships.
5
+ * Supports both local and world transforms in 4D space.
6
+ */
7
+
8
+ import { Vec4 } from '../math/Vec4.js';
9
+ import { Mat4x4 } from '../math/Mat4x4.js';
10
+ import { Rotor4D } from '../math/Rotor4D.js';
11
+
12
+ let nodeIdCounter = 0;
13
+
14
+ /**
15
+ * Generate unique node ID
16
+ * @returns {string}
17
+ */
18
+ function generateNodeId() {
19
+ return `node_${++nodeIdCounter}`;
20
+ }
21
+
22
+ /**
23
+ * Node4D class - Base scene graph node
24
+ */
25
+ export class Node4D {
26
+ /**
27
+ * @param {string} [name] - Optional node name
28
+ */
29
+ constructor(name = '') {
30
+ /** @type {string} Unique identifier */
31
+ this.id = generateNodeId();
32
+
33
+ /** @type {string} Human-readable name */
34
+ this.name = name || this.id;
35
+
36
+ /** @type {Node4D|null} Parent node */
37
+ this._parent = null;
38
+
39
+ /** @type {Node4D[]} Child nodes */
40
+ this._children = [];
41
+
42
+ /** @type {Vec4} Local position */
43
+ this._position = Vec4.zero();
44
+
45
+ /** @type {Rotor4D} Local rotation */
46
+ this._rotation = Rotor4D.identity();
47
+
48
+ /** @type {Vec4} Local scale (uniform in each dimension) */
49
+ this._scale = new Vec4(1, 1, 1, 1);
50
+
51
+ /** @type {Mat4x4} Local transform matrix (cached) */
52
+ this._localMatrix = Mat4x4.identity();
53
+
54
+ /** @type {Mat4x4} World transform matrix (cached) */
55
+ this._worldMatrix = Mat4x4.identity();
56
+
57
+ /** @type {boolean} Whether local matrix needs recalculation */
58
+ this._localDirty = true;
59
+
60
+ /** @type {boolean} Whether world matrix needs recalculation */
61
+ this._worldDirty = true;
62
+
63
+ /** @type {boolean} Whether node is visible */
64
+ this.visible = true;
65
+
66
+ /** @type {boolean} Whether node is enabled for updates */
67
+ this.enabled = true;
68
+
69
+ /** @type {Map<string, any>} User data storage */
70
+ this.userData = new Map();
71
+
72
+ /** @type {string[]} Tags for filtering */
73
+ this.tags = [];
74
+
75
+ /** @type {number} Layer mask for rendering/physics */
76
+ this.layerMask = 1;
77
+ }
78
+
79
+ // ==================== Hierarchy ====================
80
+
81
+ /**
82
+ * Get parent node
83
+ * @returns {Node4D|null}
84
+ */
85
+ get parent() {
86
+ return this._parent;
87
+ }
88
+
89
+ /**
90
+ * Set parent node
91
+ * @param {Node4D|null} newParent
92
+ */
93
+ set parent(newParent) {
94
+ if (this._parent === newParent) return;
95
+
96
+ // Remove from current parent
97
+ if (this._parent) {
98
+ const idx = this._parent._children.indexOf(this);
99
+ if (idx !== -1) {
100
+ this._parent._children.splice(idx, 1);
101
+ }
102
+ }
103
+
104
+ // Set new parent
105
+ this._parent = newParent;
106
+
107
+ // Add to new parent's children
108
+ if (newParent) {
109
+ newParent._children.push(this);
110
+ }
111
+
112
+ // Mark world transform as dirty
113
+ this._markWorldDirty();
114
+ }
115
+
116
+ /**
117
+ * Get children array (read-only copy)
118
+ * @returns {Node4D[]}
119
+ */
120
+ get children() {
121
+ return [...this._children];
122
+ }
123
+
124
+ /**
125
+ * Get number of children
126
+ * @returns {number}
127
+ */
128
+ get childCount() {
129
+ return this._children.length;
130
+ }
131
+
132
+ /**
133
+ * Add a child node
134
+ * @param {Node4D} child
135
+ * @returns {this}
136
+ */
137
+ addChild(child) {
138
+ if (child._parent === this) return this;
139
+ if (child === this) throw new Error('Cannot add node as child of itself');
140
+ if (this.isDescendantOf(child)) throw new Error('Cannot create circular hierarchy');
141
+
142
+ child.parent = this;
143
+ return this;
144
+ }
145
+
146
+ /**
147
+ * Remove a child node
148
+ * @param {Node4D} child
149
+ * @returns {boolean} True if child was removed
150
+ */
151
+ removeChild(child) {
152
+ if (child._parent !== this) return false;
153
+ child.parent = null;
154
+ return true;
155
+ }
156
+
157
+ /**
158
+ * Remove all children
159
+ * @returns {this}
160
+ */
161
+ removeAllChildren() {
162
+ for (const child of [...this._children]) {
163
+ child.parent = null;
164
+ }
165
+ return this;
166
+ }
167
+
168
+ /**
169
+ * Get child by index
170
+ * @param {number} index
171
+ * @returns {Node4D|undefined}
172
+ */
173
+ getChildAt(index) {
174
+ return this._children[index];
175
+ }
176
+
177
+ /**
178
+ * Get child by name
179
+ * @param {string} name
180
+ * @returns {Node4D|undefined}
181
+ */
182
+ getChildByName(name) {
183
+ return this._children.find(c => c.name === name);
184
+ }
185
+
186
+ /**
187
+ * Find descendant by name (recursive)
188
+ * @param {string} name
189
+ * @returns {Node4D|undefined}
190
+ */
191
+ findByName(name) {
192
+ if (this.name === name) return this;
193
+ for (const child of this._children) {
194
+ const found = child.findByName(name);
195
+ if (found) return found;
196
+ }
197
+ return undefined;
198
+ }
199
+
200
+ /**
201
+ * Find all descendants with tag
202
+ * @param {string} tag
203
+ * @returns {Node4D[]}
204
+ */
205
+ findByTag(tag) {
206
+ const results = [];
207
+ if (this.tags.includes(tag)) results.push(this);
208
+ for (const child of this._children) {
209
+ results.push(...child.findByTag(tag));
210
+ }
211
+ return results;
212
+ }
213
+
214
+ /**
215
+ * Check if this node is descendant of another
216
+ * @param {Node4D} ancestor
217
+ * @returns {boolean}
218
+ */
219
+ isDescendantOf(ancestor) {
220
+ let current = this._parent;
221
+ while (current) {
222
+ if (current === ancestor) return true;
223
+ current = current._parent;
224
+ }
225
+ return false;
226
+ }
227
+
228
+ /**
229
+ * Get root node of hierarchy
230
+ * @returns {Node4D}
231
+ */
232
+ getRoot() {
233
+ let current = this;
234
+ while (current._parent) {
235
+ current = current._parent;
236
+ }
237
+ return current;
238
+ }
239
+
240
+ /**
241
+ * Get depth in hierarchy (root = 0)
242
+ * @returns {number}
243
+ */
244
+ getDepth() {
245
+ let depth = 0;
246
+ let current = this._parent;
247
+ while (current) {
248
+ depth++;
249
+ current = current._parent;
250
+ }
251
+ return depth;
252
+ }
253
+
254
+ // ==================== Transform ====================
255
+
256
+ /**
257
+ * Get local position
258
+ * @returns {Vec4}
259
+ */
260
+ get position() {
261
+ return this._position;
262
+ }
263
+
264
+ /**
265
+ * Set local position
266
+ * @param {Vec4} value
267
+ */
268
+ set position(value) {
269
+ this._position = value;
270
+ this._markLocalDirty();
271
+ }
272
+
273
+ /**
274
+ * Get local rotation
275
+ * @returns {Rotor4D}
276
+ */
277
+ get rotation() {
278
+ return this._rotation;
279
+ }
280
+
281
+ /**
282
+ * Set local rotation
283
+ * @param {Rotor4D} value
284
+ */
285
+ set rotation(value) {
286
+ this._rotation = value;
287
+ this._markLocalDirty();
288
+ }
289
+
290
+ /**
291
+ * Get local scale
292
+ * @returns {Vec4}
293
+ */
294
+ get scale() {
295
+ return this._scale;
296
+ }
297
+
298
+ /**
299
+ * Set local scale
300
+ * @param {Vec4} value
301
+ */
302
+ set scale(value) {
303
+ this._scale = value;
304
+ this._markLocalDirty();
305
+ }
306
+
307
+ /**
308
+ * Set position components directly
309
+ * @param {number} x
310
+ * @param {number} y
311
+ * @param {number} z
312
+ * @param {number} w
313
+ * @returns {this}
314
+ */
315
+ setPosition(x, y, z, w) {
316
+ this._position = new Vec4(x, y, z, w);
317
+ this._markLocalDirty();
318
+ return this;
319
+ }
320
+
321
+ /**
322
+ * Set uniform scale
323
+ * @param {number} s
324
+ * @returns {this}
325
+ */
326
+ setUniformScale(s) {
327
+ this._scale = new Vec4(s, s, s, s);
328
+ this._markLocalDirty();
329
+ return this;
330
+ }
331
+
332
+ /**
333
+ * Translate by offset
334
+ * @param {Vec4} offset
335
+ * @returns {this}
336
+ */
337
+ translate(offset) {
338
+ this._position = this._position.add(offset);
339
+ this._markLocalDirty();
340
+ return this;
341
+ }
342
+
343
+ /**
344
+ * Rotate by rotor
345
+ * @param {Rotor4D} rotor
346
+ * @returns {this}
347
+ */
348
+ rotate(rotor) {
349
+ this._rotation = rotor.multiply(this._rotation).normalize();
350
+ this._markLocalDirty();
351
+ return this;
352
+ }
353
+
354
+ /**
355
+ * Rotate around a plane
356
+ * @param {string} plane - 'XY', 'XZ', 'YZ', 'XW', 'YW', 'ZW'
357
+ * @param {number} angle - Radians
358
+ * @returns {this}
359
+ */
360
+ rotateOnPlane(plane, angle) {
361
+ const rotor = Rotor4D.fromPlaneAngle(plane, angle);
362
+ return this.rotate(rotor);
363
+ }
364
+
365
+ /**
366
+ * Get local transform matrix
367
+ * @returns {Mat4x4}
368
+ */
369
+ get localMatrix() {
370
+ if (this._localDirty) {
371
+ this._updateLocalMatrix();
372
+ }
373
+ return this._localMatrix;
374
+ }
375
+
376
+ /**
377
+ * Get world transform matrix
378
+ * @returns {Mat4x4}
379
+ */
380
+ get worldMatrix() {
381
+ if (this._worldDirty) {
382
+ this._updateWorldMatrix();
383
+ }
384
+ return this._worldMatrix;
385
+ }
386
+
387
+ /**
388
+ * Get world position
389
+ * @returns {Vec4}
390
+ */
391
+ get worldPosition() {
392
+ const wm = this.worldMatrix;
393
+ return new Vec4(wm.get(0, 3), wm.get(1, 3), wm.get(2, 3), wm.get(3, 3));
394
+ }
395
+
396
+ /**
397
+ * Set world position (adjusts local position)
398
+ * @param {Vec4} worldPos
399
+ * @returns {this}
400
+ */
401
+ setWorldPosition(worldPos) {
402
+ if (this._parent) {
403
+ const parentWorldInv = this._parent.worldMatrix.inverse();
404
+ this._position = parentWorldInv.multiplyVec4(worldPos);
405
+ } else {
406
+ this._position = worldPos;
407
+ }
408
+ this._markLocalDirty();
409
+ return this;
410
+ }
411
+
412
+ /**
413
+ * Transform a point from local to world space
414
+ * Note: In 4D, we can't use homogeneous coordinates for translation
415
+ * since W is a spatial dimension. We apply rotation/scale via the
416
+ * rotation part of the matrix, then add world position separately.
417
+ * @param {Vec4} localPoint
418
+ * @returns {Vec4}
419
+ */
420
+ localToWorld(localPoint) {
421
+ // Get local rotation/scale only (exclude translation)
422
+ // by using the rotation rotor directly
423
+ const scaledPoint = new Vec4(
424
+ localPoint.x * this._scale.x,
425
+ localPoint.y * this._scale.y,
426
+ localPoint.z * this._scale.z,
427
+ localPoint.w * this._scale.w
428
+ );
429
+
430
+ // Apply rotation
431
+ const rotated = this._rotation.rotate(scaledPoint);
432
+
433
+ // Add local position
434
+ const localResult = rotated.add(this._position);
435
+
436
+ // If has parent, transform through parent
437
+ if (this._parent) {
438
+ return this._parent.localToWorld(localResult);
439
+ }
440
+
441
+ return localResult;
442
+ }
443
+
444
+ /**
445
+ * Transform a point from world to local space
446
+ * @param {Vec4} worldPoint
447
+ * @returns {Vec4}
448
+ */
449
+ worldToLocal(worldPoint) {
450
+ return this.worldMatrix.inverse().multiplyVec4(worldPoint);
451
+ }
452
+
453
+ /**
454
+ * Look at a target position (aligns +Z toward target)
455
+ * Note: In 4D this is more complex - this is a simplified version
456
+ * @param {Vec4} target
457
+ * @returns {this}
458
+ */
459
+ lookAt(target) {
460
+ const direction = target.sub(this.worldPosition).normalize();
461
+ // Simplified: rotate to align with direction
462
+ // Full 4D lookAt would require specifying an "up" and "ana" vector
463
+ const forward = new Vec4(0, 0, 1, 0);
464
+ const dot = forward.dot(direction);
465
+ if (Math.abs(dot) < 0.9999) {
466
+ const angle = Math.acos(dot);
467
+ // Use XZ and YZ planes for 3D-like rotation
468
+ const rotX = Math.atan2(direction.y, direction.z);
469
+ const rotY = Math.atan2(direction.x, direction.z);
470
+ this._rotation = Rotor4D.fromEuler6(rotX, rotY, 0, 0, 0, 0);
471
+ this._markLocalDirty();
472
+ }
473
+ return this;
474
+ }
475
+
476
+ // ==================== Internal ====================
477
+
478
+ /**
479
+ * Mark local matrix as dirty
480
+ * @private
481
+ */
482
+ _markLocalDirty() {
483
+ this._localDirty = true;
484
+ this._markWorldDirty();
485
+ }
486
+
487
+ /**
488
+ * Mark world matrix as dirty (cascades to children)
489
+ * @private
490
+ */
491
+ _markWorldDirty() {
492
+ this._worldDirty = true;
493
+ for (const child of this._children) {
494
+ child._markWorldDirty();
495
+ }
496
+ }
497
+
498
+ /**
499
+ * Update local transform matrix
500
+ * @private
501
+ */
502
+ _updateLocalMatrix() {
503
+ // Start with identity
504
+ this._localMatrix = Mat4x4.identity();
505
+
506
+ // Apply scale
507
+ const scaleMatrix = Mat4x4.identity();
508
+ scaleMatrix.set(0, 0, this._scale.x);
509
+ scaleMatrix.set(1, 1, this._scale.y);
510
+ scaleMatrix.set(2, 2, this._scale.z);
511
+ scaleMatrix.set(3, 3, this._scale.w);
512
+
513
+ // Apply rotation (toMatrix returns Float32Array, wrap in Mat4x4)
514
+ const rotationMatrix = new Mat4x4(this._rotation.toMatrix());
515
+
516
+ // Apply translation (in 4D, translation is stored in last column, keep [3,3]=1)
517
+ const translationMatrix = Mat4x4.identity();
518
+ translationMatrix.set(0, 3, this._position.x);
519
+ translationMatrix.set(1, 3, this._position.y);
520
+ translationMatrix.set(2, 3, this._position.z);
521
+ // Note: position.w is the 4th spatial coordinate, handled separately
522
+ // Matrix[3,3] must remain 1 for proper transformation
523
+
524
+ // Compose: T * R * S
525
+ this._localMatrix = translationMatrix.multiply(rotationMatrix).multiply(scaleMatrix);
526
+ this._localDirty = false;
527
+ }
528
+
529
+ /**
530
+ * Update world transform matrix
531
+ * @private
532
+ */
533
+ _updateWorldMatrix() {
534
+ if (this._localDirty) {
535
+ this._updateLocalMatrix();
536
+ }
537
+
538
+ if (this._parent) {
539
+ this._worldMatrix = this._parent.worldMatrix.multiply(this._localMatrix);
540
+ } else {
541
+ this._worldMatrix = this._localMatrix.clone();
542
+ }
543
+
544
+ this._worldDirty = false;
545
+ }
546
+
547
+ // ==================== Traversal ====================
548
+
549
+ /**
550
+ * Traverse hierarchy depth-first
551
+ * @param {function(Node4D): boolean|void} callback - Return false to stop
552
+ * @returns {boolean} True if completed, false if stopped
553
+ */
554
+ traverse(callback) {
555
+ if (callback(this) === false) return false;
556
+ for (const child of this._children) {
557
+ if (!child.traverse(callback)) return false;
558
+ }
559
+ return true;
560
+ }
561
+
562
+ /**
563
+ * Traverse hierarchy breadth-first
564
+ * @param {function(Node4D): boolean|void} callback
565
+ * @returns {boolean}
566
+ */
567
+ traverseBreadthFirst(callback) {
568
+ const queue = [this];
569
+ while (queue.length > 0) {
570
+ const node = queue.shift();
571
+ if (callback(node) === false) return false;
572
+ queue.push(...node._children);
573
+ }
574
+ return true;
575
+ }
576
+
577
+ /**
578
+ * Traverse only visible nodes
579
+ * @param {function(Node4D): void} callback
580
+ */
581
+ traverseVisible(callback) {
582
+ if (!this.visible) return;
583
+ callback(this);
584
+ for (const child of this._children) {
585
+ child.traverseVisible(callback);
586
+ }
587
+ }
588
+
589
+ /**
590
+ * Get all descendants as flat array
591
+ * @returns {Node4D[]}
592
+ */
593
+ getDescendants() {
594
+ const result = [];
595
+ this.traverse(node => {
596
+ if (node !== this) result.push(node);
597
+ });
598
+ return result;
599
+ }
600
+
601
+ // ==================== Lifecycle ====================
602
+
603
+ /**
604
+ * Clone this node (without children)
605
+ * @returns {Node4D}
606
+ */
607
+ clone() {
608
+ const cloned = new Node4D(this.name + '_clone');
609
+ cloned._position = this._position.clone();
610
+ cloned._rotation = this._rotation.clone();
611
+ cloned._scale = this._scale.clone();
612
+ cloned.visible = this.visible;
613
+ cloned.enabled = this.enabled;
614
+ cloned.tags = [...this.tags];
615
+ cloned.layerMask = this.layerMask;
616
+ return cloned;
617
+ }
618
+
619
+ /**
620
+ * Clone this node with all descendants
621
+ * @returns {Node4D}
622
+ */
623
+ cloneDeep() {
624
+ const cloned = this.clone();
625
+ for (const child of this._children) {
626
+ cloned.addChild(child.cloneDeep());
627
+ }
628
+ return cloned;
629
+ }
630
+
631
+ /**
632
+ * Dispose this node and remove from parent
633
+ */
634
+ dispose() {
635
+ this.removeAllChildren();
636
+ if (this._parent) {
637
+ this._parent.removeChild(this);
638
+ }
639
+ this.userData.clear();
640
+ }
641
+
642
+ /**
643
+ * Dispose this node and all descendants
644
+ */
645
+ disposeDeep() {
646
+ for (const child of [...this._children]) {
647
+ child.disposeDeep();
648
+ }
649
+ this.dispose();
650
+ }
651
+
652
+ // ==================== Serialization ====================
653
+
654
+ /**
655
+ * Serialize node to plain object
656
+ * @returns {object}
657
+ */
658
+ toJSON() {
659
+ return {
660
+ id: this.id,
661
+ name: this.name,
662
+ position: [this._position.x, this._position.y, this._position.z, this._position.w],
663
+ rotation: this._rotation.toArray(),
664
+ scale: [this._scale.x, this._scale.y, this._scale.z, this._scale.w],
665
+ visible: this.visible,
666
+ enabled: this.enabled,
667
+ tags: this.tags,
668
+ layerMask: this.layerMask,
669
+ children: this._children.map(c => c.toJSON())
670
+ };
671
+ }
672
+
673
+ /**
674
+ * Create node from plain object
675
+ * @param {object} json
676
+ * @returns {Node4D}
677
+ */
678
+ static fromJSON(json) {
679
+ const node = new Node4D(json.name);
680
+ node._position = new Vec4(...json.position);
681
+ node._rotation = Rotor4D.fromArray(json.rotation);
682
+ node._scale = new Vec4(...json.scale);
683
+ node.visible = json.visible;
684
+ node.enabled = json.enabled;
685
+ node.tags = json.tags || [];
686
+ node.layerMask = json.layerMask || 1;
687
+ node._markLocalDirty();
688
+
689
+ for (const childJson of (json.children || [])) {
690
+ node.addChild(Node4D.fromJSON(childJson));
691
+ }
692
+
693
+ return node;
694
+ }
695
+ }
696
+
697
+ export default Node4D;