@fusefactory/fuse-three-forcegraph 1.0.5 → 1.0.7

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 (4) hide show
  1. package/README.md +61 -43
  2. package/dist/index.d.mts +1551 -1540
  3. package/dist/index.mjs +4535 -4446
  4. package/package.json +46 -46
package/README.md CHANGED
@@ -15,25 +15,33 @@ A high-performance GPU-accelerated force-directed graph visualization library bu
15
15
  ### Core Components
16
16
 
17
17
  #### Engine (`core/Engine.ts`)
18
+
18
19
  The main orchestrator that owns and coordinates all components:
20
+
19
21
  - Manages shared GPU buffers (SimulationBuffers, StaticAssets, PickBuffer)
20
22
  - Coordinates GraphStore, GraphScene, and ForceSimulation
21
23
  - Handles the render loop and user interactions
22
24
 
23
25
  #### SimulationBuffers (`textures/SimulationBuffers.ts`)
26
+
24
27
  Manages dynamic render targets updated by force simulation:
28
+
25
29
  - Position buffers (current, previous, original) for ping-pong rendering
26
30
  - Velocity buffers for force accumulation
27
31
  - Automatically sizes textures based on node count
28
32
 
29
33
  #### StaticAssets (`textures/StaticAssets.ts`)
34
+
30
35
  Manages read-only GPU textures:
36
+
31
37
  - Node radii and colors
32
38
  - Link indices and properties
33
39
  - Created once at initialization, updated only on mode changes
34
40
 
35
41
  #### GraphScene (`rendering/GraphScene.ts`)
42
+
36
43
  Manages the 3D scene and visual rendering:
44
+
37
45
  - Node and link renderers
38
46
  - Camera controls
39
47
  - Visual mode application
@@ -43,7 +51,9 @@ Manages the 3D scene and visual rendering:
43
51
  The simulation uses a **pass-based architecture** where each force type is implemented as an independent pass:
44
52
 
45
53
  #### BasePass (`simulation/BasePass.ts`)
54
+
46
55
  Abstract base class for all force passes. Provides:
56
+
47
57
  - Material management
48
58
  - Uniform updates
49
59
  - Enable/disable control
@@ -63,7 +73,9 @@ Located in `simulation/passes/`:
63
73
  8. **IntegratePass** - Updates positions from velocities
64
74
 
65
75
  #### ForceSimulation (`simulation/ForceSimulation.ts`)
76
+
66
77
  Manages and executes force passes:
78
+
67
79
  ```typescript
68
80
  // Add custom force pass
69
81
  simulation.addPass('myForce', new MyCustomPass(config))
@@ -121,43 +133,42 @@ engine.setData(graphData)
121
133
  // Start simulation and rendering
122
134
  engine.start()
123
135
 
124
- GRAPH.styleRegistry.setNodeStyles({
125
- 'root': { color: 0xE53E3E, size: 55 },
126
- 'series': { color: 0x38A169, size: 33 },
127
- 'artwork': { color: 0x3182CE, size: 22 },
128
- })
129
-
130
- // Get simulation config - direct access, changes take effect immediately
131
- const simulation = engine.getSimulation()
132
- const config = simulation.config
136
+ GRAPH.styleRegistry.setNodeStyles({
137
+ root: { color: 0xE53E3E, size: 55 },
138
+ series: { color: 0x38A169, size: 33 },
139
+ artwork: { color: 0x3182CE, size: 22 },
140
+ })
133
141
 
134
- // Create Tweakpane
135
- pane = new Pane()
142
+ // Get simulation config - direct access, changes take effect immediately
143
+ const simulation = engine.getSimulation()
144
+ const config = simulation.config
136
145
 
137
- // Bind simulation parameters - changes to config work directly, no sync needed
138
- const simFolder = pane.addFolder({ title: 'Simulation' })
139
- simFolder.addBinding(config, 'alpha', { min: 0, max: 1 })
140
- simFolder.addBinding(config, 'alphaDecay', { min: 0, max: 0.1 })
141
- simFolder.addBinding(config, 'damping', { min: 0, max: 1 })
146
+ // Create Tweakpane
147
+ pane = new Pane()
142
148
 
143
- // Many-body force, check uniforms that can be added in binding...
144
- const manyBodyFolder = pane.addFolder({ title: 'Many-Body Force' })
145
- manyBodyFolder.addBinding(config, 'enableManyBody')
146
- manyBodyFolder.addBinding(config, 'manyBodyStrength', { min: 0, max: 100 })
149
+ // Bind simulation parameters - changes to config work directly, no sync needed
150
+ const simFolder = pane.addFolder({ title: 'Simulation' })
151
+ simFolder.addBinding(config, 'alpha', { min: 0, max: 1 })
152
+ simFolder.addBinding(config, 'alphaDecay', { min: 0, max: 0.1 })
153
+ simFolder.addBinding(config, 'damping', { min: 0, max: 1 })
147
154
 
155
+ // Many-body force, check uniforms that can be added in binding...
156
+ const manyBodyFolder = pane.addFolder({ title: 'Many-Body Force' })
157
+ manyBodyFolder.addBinding(config, 'enableManyBody')
158
+ manyBodyFolder.addBinding(config, 'manyBodyStrength', { min: 0, max: 100 })
148
159
 
149
- // Set up attractors - each pulls specific categories
150
- simulation.setAttractors([
160
+ // Set up attractors - each pulls specific categories
161
+ simulation.setAttractors([
151
162
  {
152
163
  id: 'center',
153
164
  position: { x: 0, y: 0.0, z: 0 },
154
- categories: ['root'],
155
- strength: 55.
156
- },])
157
-
158
- // Adjust global attractor strength
159
- simulation.config.attractorStrength = 0.03
165
+ categories: ['root'],
166
+ strength: 55.0
167
+ },
168
+ ])
160
169
 
170
+ // Adjust global attractor strength
171
+ simulation.config.attractorStrength = 0.03
161
172
 
162
173
  ```
163
174
 
@@ -167,9 +178,9 @@ For testing and prototyping, you can generate random graph data:
167
178
 
168
179
  ```typescript
169
180
  // Utility function to create random nodes and links
170
- const createRandomData = (nodeCount: number = 10, linkCount: number = 15) => {
181
+ function createRandomData(nodeCount: number = 10, linkCount: number = 15) {
171
182
  const groups = ['root', 'series', 'artwork', 'character', 'location']
172
-
183
+
173
184
  // Generate random nodes
174
185
  const nodes = Array.from({ length: nodeCount }, (_, i) => ({
175
186
  id: (i + 1).toString(),
@@ -178,23 +189,23 @@ const createRandomData = (nodeCount: number = 10, linkCount: number = 15) => {
178
189
  y: (Math.random() - 0.5) * 2,
179
190
  z: (Math.random() - 0.5) * 2
180
191
  }))
181
-
192
+
182
193
  // Generate random links
183
194
  const links = Array.from({ length: linkCount }, () => {
184
195
  const sourceId = Math.floor(Math.random() * nodeCount) + 1
185
196
  let targetId = Math.floor(Math.random() * nodeCount) + 1
186
-
197
+
187
198
  // Ensure source and target are different
188
199
  while (targetId === sourceId) {
189
200
  targetId = Math.floor(Math.random() * nodeCount) + 1
190
201
  }
191
-
202
+
192
203
  return {
193
204
  source: sourceId.toString(),
194
205
  target: targetId.toString()
195
206
  }
196
207
  })
197
-
208
+
198
209
  return { nodes, links }
199
210
  }
200
211
 
@@ -205,7 +216,8 @@ engine.setData(createRandomData(100, 70))
205
216
  ### Custom Force Pass
206
217
 
207
218
  ```typescript
208
- import { BasePass, type PassContext } from './simulation/BasePass'
219
+ import type { PassContext } from './simulation/BasePass'
220
+ import { BasePass } from './simulation/BasePass'
209
221
 
210
222
  class CustomForcePass extends BasePass {
211
223
  private strength: number = 1.0
@@ -228,12 +240,13 @@ class CustomForcePass extends BasePass {
228
240
  }
229
241
 
230
242
  updateUniforms(context: PassContext): void {
231
- if (!this.material) return
232
-
233
- this.material.uniforms.uPositionsTexture.value =
234
- context.simBuffers.getCurrentPositionTexture()
235
- this.material.uniforms.uVelocityTexture.value =
236
- context.simBuffers.getCurrentVelocityTexture()
243
+ if (!this.material)
244
+ return
245
+
246
+ this.material.uniforms.uPositionsTexture.value
247
+ = context.simBuffers.getCurrentPositionTexture()
248
+ this.material.uniforms.uVelocityTexture.value
249
+ = context.simBuffers.getCurrentVelocityTexture()
237
250
  this.material.uniforms.uAlpha.value = context.alpha
238
251
  this.material.uniforms.uStrength.value = this.strength
239
252
  }
@@ -309,12 +322,14 @@ fuse-three-forcegraph/
309
322
  ## GPU Texture Layout
310
323
 
311
324
  ### Position/Velocity Buffers
325
+
312
326
  - Format: `RGBA Float`
313
327
  - Layout: Grid where each pixel = one node
314
328
  - Channels: `(x, y, z, unused)`
315
329
  - Size: Next power-of-2 square ≥ √nodeCount
316
330
 
317
331
  ### Static Assets
332
+
318
333
  - **Radii**: `Red Float` (1 channel)
319
334
  - **Colors**: `RGBA Float` (4 channels)
320
335
  - **Link Indices**: `RGBA Float` (source_x, source_y, target_x, target_y)
@@ -332,9 +347,10 @@ fuse-three-forcegraph/
332
347
  The library implements a three-tiered interaction system for progressive engagement:
333
348
 
334
349
  ### 1. Hover
350
+
335
351
  - **Trigger**: Mouse cursor enters node boundary
336
352
  - **Purpose**: Lightweight preview and visual feedback
337
- - **Response**:
353
+ - **Response**:
338
354
  - Node highlight/glow effect
339
355
  - Cursor change
340
356
  - Optional tooltip display
@@ -342,6 +358,7 @@ The library implements a three-tiered interaction system for progressive engagem
342
358
  - **Use Case**: Quick scanning and exploration
343
359
 
344
360
  ### 2. Pop (Dwell/Long Hover)
361
+
345
362
  - **Trigger**: Cursor remains over node for defined duration (e.g., 500ms)
346
363
  - **Purpose**: Detailed information display without commitment
347
364
  - **Response**:
@@ -352,6 +369,7 @@ The library implements a three-tiered interaction system for progressive engagem
352
369
  - **Use Case**: Examining node details and immediate connections
353
370
 
354
371
  ### 3. Click
372
+
355
373
  - **Trigger**: Primary mouse button click on node
356
374
  - **Purpose**: Full interaction and state change
357
375
  - **Response**:
@@ -363,6 +381,7 @@ The library implements a three-tiered interaction system for progressive engagem
363
381
  - **Use Case**: Focused analysis and permanent selection
364
382
 
365
383
  ### Interaction Pipeline
384
+
366
385
  ```typescript
367
386
  // Hover
368
387
  interactionManager.on('hover', ({ node, position }) => {
@@ -394,4 +413,3 @@ This progressive disclosure pattern prevents overwhelming users while enabling d
394
413
  - **three.js** - 3D rendering engine
395
414
  - **camera-controls** - Camera manipulation
396
415
  - **gsap** - Animation and transitions
397
-