avbd-babylon 0.3.0 → 0.4.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/docs/HPLOC.md CHANGED
@@ -1,116 +1,120 @@
1
- # GPU tree collision detection
2
-
3
- `GpuHploc` in `gpuHploc.js` builds and traverses a GPU bounding-volume hierarchy.
4
- Its pairs feed the existing narrowphase and AVBD solver. Shapes, friction,
5
- rotation, solving rounds and contact equations stay the same; pinned upstream
6
- sources remain unchanged.
7
-
8
- This is a portable hierarchical PLOC treelet variant, based on the clustering
9
- family described in [H-PLOC](https://gpuopen.com/download/HPLOC.pdf), **not** the
10
- paper's single-launch wave implementation. `hplocpp.wgsl` builds the tree;
11
- `hplocSort.wgsl` sorts keys.
12
-
13
- ## Algorithm
14
-
15
- 1. Compute world AABBs from live GPU positions, quaternions and collider sizes.
16
- 2. Reduce scene bounds on the GPU, generate 30-bit Morton keys and sort them
17
- with stable radix passes. No fixed scene coordinates or lost duplicate keys.
18
- 3. Merge mutual nearest neighbours by surface-area cost in 16-cluster treelets.
19
- Construct hierarchy levels until one root remains. Dispatch boundaries
20
- publish global writes; barriers publish local merges. There are no
21
- cross-workgroup spin waits or relaxed-atomic publication assumptions.
22
- 4. Build escape links for stackless traversal. Dynamic queries find static and
23
- kinematic leaves; giant ground slabs do not traverse the whole tree.
24
- 5. Refit **every leaf and internal bound every step**. Rebuild ordering and
25
- clustering every 64 steps by default. Refitting preserves coverage after
26
- teleports; rebuilding improves traversal quality.
27
-
28
- Pair acceptance reuses the grid's masks, disabled-joint handling, bounding
29
- spheres, world AABBs, face-axis rejection and overflow accounting. Dynamic
30
- pairs are emitted once; dynamic/static pairs are emitted from the dynamic
31
- body. Hulls retain the canonical hull narrowphase.
32
-
33
- ## Selection and limits
34
-
35
- `AppGpuSolver3D` and `AvbdPhysics.create` accept `broadphase: "auto"`, `"grid"`
36
- or `"hploc"`, and `bvh: { rebuildInterval: 64 }`. The lab and browser benchmark
37
- have the same choices. Explicit selections let you compare on your GPU.
38
-
39
- Automatic selection uses a tree for at least 10,000 bodies when either:
40
-
41
- - Grid cells are at least four times a typical body's bounding-sphere diameter.
42
- - At least a quarter of dynamic bodies are thin plates, and there is at least
43
- one active constraint per body. This covers the rigid ragdoll net.
44
-
45
- For this policy, a thin plate has a shortest dimension no more than 40% of its
46
- middle dimension, with the middle dimension at least half the longest. Rods,
47
- spheres and convex hulls do not qualify as plates. Shape metadata is checked
48
- when bodies or active constraint counts change; positions are not downloaded.
49
-
50
- Body count alone does not select a tree. Adapter dispatch/storage limits are checked; automatic mode
51
- keeps the grid when unsupported. Explicit unsupported requests fail clearly.
52
-
53
- This is a conservative policy based on the measured 1K, 10K and 50K mixed-size workloads and the 24K ragdoll net,
54
- not a universal crossover point. Scene layout, size distribution and GPU matter.
55
-
56
- Extra buffers store nodes, links, sorting and clustering. JSON records primary
57
- buffer bytes, rebuild/refit counts and the first GPU step. Startup GPU time
58
- excludes CPU scene creation and shader compilation. Warm timing includes
59
- periodic rebuilds, but excludes the first build; inspect both. Grid buffers
60
- remain available for selection changes. This path adds no sleeping.
61
- Reported primary bytes exclude prefix-scan scratch, small uniforms and pipelines.
62
-
63
- ## Replication and checks
64
-
65
- Open `/tests/performance.html` and close other GPU workloads. Paired comparison
66
- alternates execution order every step and preserves each scene's settings.
67
- Every step checks overflow and solve-group conflicts.
68
-
69
- ```js
70
- try {
71
- const result = await __PERFORMANCE__.runPaired(
72
- "3d-mixed-sizes-50k",
73
- ["grid", "hploc"],
74
- 60,
75
- 60,
76
- );
77
- console.table(
78
- result.results.map((r) => ({
79
- method: r.broadphase,
80
- collisionMs: r.summary.collision.mean,
81
- physicsMs: r.summary.total.mean,
82
- extraBytes: r.bvh?.extraBytes ?? 0,
83
- })),
84
- );
85
- } finally {
86
- await __BENCHMARK_VIEW__.preview.load(document.querySelector("#scene").value);
87
- }
88
- ```
89
-
90
- Use `grid-detail` / `hploc-detail` to separate build/refit, pair search,
91
- narrowphase, body solving and contact-force updates. Extra pass boundaries
92
- affect timing, so compare matching detailed modes. Raw data retains rebuild
93
- spikes and noisy samples. An unchanged solve-stage difference over 10% is flagged.
94
-
95
- For the ragdoll net, compare `"showcase-ragdolls-on-cloth-24k"` with
96
- `["grid", "hploc"]`, 1440 warmup steps and 60 samples. This measures the scene
97
- after six simulated seconds at its full 240 Hz collision rate. Saved paired
98
- results on the RTX 4070 Laptop GPU use the same timestep and five AVBD iterations;
99
- see `test-results/solver-ragdoll-settled.json`. The separate
100
- `node scripts/check-ragdoll-net.mjs` regression checks every quarter-second
101
- through 30 simulated seconds with automatic selection. It checks whole limbs
102
- below the sheet and partial capsule/triangle intersections deeper than 5 mm.
103
- The net uses overlapping plates and excludes its eight immediate neighbors
104
- from self-collisions; distant folds still collide.
105
-
106
- Tests compare unique, complete pair sets against the grid for empty and partial
107
- treelets, duplicate keys, rotated hulls and boxes, spheres, giant statics,
108
- ignored and released joints, filters, teleports and added bodies. Physical regressions cover floor support,
109
- joints, sleeping and support removal; browser checks exercise motion and drawing.
110
-
111
- `node scripts/check-hploc-motion.mjs` checks 360 steps of the 10K/50K mixed-size
112
- scenes, 110K ring, 100K columns and half-million walls with the tree forced.
113
- It checks every step's capacity and scheduling counters, measures floor support
114
- and rotation, and captures four screenshots per scene. `npm run test:web`
115
- includes this check alongside all scene and benchmark views.
1
+ # GPU tree collision detection
116
2
 
3
+ [`GpuHploc`](../src/gpu/gpuHploc.js) in `src/gpu/` builds and traverses a GPU bounding-volume hierarchy.
4
+ Its pairs feed the existing narrowphase and AVBD solver. Shapes, friction,
5
+ rotation, solving rounds and contact equations stay the same; pinned upstream
6
+ sources remain unchanged.
7
+
8
+ This portable hierarchical PLOC treelet variant builds on the clustering family
9
+ described in [H-PLOC](https://gpuopen.com/download/HPLOC.pdf). It uses multiple
10
+ GPU dispatches to coordinate tree levels. `hplocpp.wgsl` builds the tree;
11
+ `hplocSort.wgsl` sorts keys.
12
+
13
+ ## Algorithm
14
+
15
+ 1. Compute world AABBs from live GPU positions, quaternions and collider sizes.
16
+ 2. Reduce scene bounds on the GPU, generate 30-bit Morton keys and sort them
17
+ with stable radix passes. No fixed scene coordinates or lost duplicate keys.
18
+ 3. Merge mutual nearest neighbours by surface-area cost in 16-cluster treelets.
19
+ Construct hierarchy levels until one root remains. Dispatch boundaries
20
+ publish global writes; barriers publish local merges. There are no
21
+ cross-workgroup spin waits or relaxed-atomic publication assumptions.
22
+ 4. Build escape links for stackless traversal. Dynamic queries find static and
23
+ kinematic leaves; giant ground slabs do not traverse the whole tree.
24
+ 5. Refit **every leaf and internal bound every step**. Rebuild ordering and
25
+ clustering every 64 steps by default. Refitting preserves coverage after
26
+ teleports; rebuilding improves traversal quality.
27
+
28
+ Refit steps update leaf boxes directly without the scene-bound reductions used
29
+ for Morton sorting. Every leaf and internal box still follows the current GPU
30
+ pose, including moved static bodies and teleports.
31
+
32
+ Pair acceptance reuses the grid's masks, disabled-joint handling, bounding
33
+ spheres, world AABBs, face-axis rejection and overflow accounting. Dynamic
34
+ pairs are emitted once; dynamic/static pairs are emitted from the dynamic
35
+ body. Hulls retain the canonical hull narrowphase.
36
+
37
+ ## Selection and limits
38
+
39
+ `AppGpuSolver3D` and `AvbdPhysics.create` accept `broadphase: "auto"`, `"grid"`
40
+ or `"hploc"`, and `bvh: { rebuildInterval: 64 }`. The lab and browser benchmark
41
+ have the same choices. Explicit selections let you compare on your GPU.
42
+
43
+ Automatic selection uses a tree for at least 10,000 bodies when either:
44
+
45
+ - Grid cells are at least four times a typical body's bounding-sphere diameter.
46
+ - At least a quarter of dynamic bodies are thin plates, and there is at least
47
+ one active constraint per body. This covers the rigid ragdoll net.
48
+
49
+ For this policy, a thin plate has a shortest dimension no more than 40% of its
50
+ middle dimension, with the middle dimension at least half the longest. Rods,
51
+ spheres and convex hulls do not qualify as plates. Shape metadata is checked
52
+ when bodies or active constraint counts change; positions are not downloaded.
53
+
54
+ Body count alone does not select a tree. Adapter dispatch/storage limits are checked; automatic mode
55
+ keeps the grid when unsupported. Explicit unsupported requests fail clearly.
56
+
57
+ The selection policy uses measurements from 1K, 10K and 50K mixed-size workloads
58
+ and the 24K ragdoll net. The crossover depends on scene layout, object sizes and
59
+ the GPU.
60
+
61
+ Extra buffers store nodes, links, sorting and clustering. JSON records primary
62
+ buffer bytes, rebuild/refit counts and the first GPU step. Startup GPU time
63
+ excludes CPU scene creation and shader compilation. Warm timing includes
64
+ periodic rebuilds, but excludes the first build; inspect both. Grid buffers
65
+ remain available for selection changes. Sleeping is configured separately from collision search.
66
+ Reported primary bytes exclude prefix-scan scratch, small uniforms and pipelines.
67
+
68
+ ## Replication and checks
69
+
70
+ Open `/tests/performance.html` and close other GPU workloads. Paired comparison
71
+ alternates execution order every step and preserves each scene's settings.
72
+ Every step checks overflow and solve-group conflicts.
73
+
74
+ ```js
75
+ try {
76
+ const result = await __PERFORMANCE__.runPaired(
77
+ "3d-mixed-sizes-50k",
78
+ ["grid", "hploc"],
79
+ 60,
80
+ 60,
81
+ );
82
+ console.table(
83
+ result.results.map((r) => ({
84
+ method: r.broadphase,
85
+ collisionMs: r.summary.collision.mean,
86
+ physicsMs: r.summary.total.mean,
87
+ extraBytes: r.bvh?.extraBytes ?? 0,
88
+ })),
89
+ );
90
+ } finally {
91
+ await __BENCHMARK_VIEW__.preview.load(document.querySelector("#scene").value);
92
+ }
93
+ ```
94
+
95
+ Use `grid-detail` / `hploc-detail` to separate build/refit, pair search,
96
+ narrowphase, body solving and contact-force updates. Extra pass boundaries
97
+ affect timing, so compare matching detailed modes. Raw data retains rebuild
98
+ spikes and noisy samples. An unchanged solve-stage difference over 10% is flagged.
99
+
100
+ For the ragdoll net, compare `"showcase-ragdolls-on-cloth-24k"` with
101
+ `["grid", "hploc"]`, 1440 warmup steps and 60 samples. This measures the scene
102
+ after six simulated seconds at its full 240 Hz collision rate. Saved paired
103
+ results on the RTX 4070 Laptop GPU use the same timestep and five AVBD iterations;
104
+ see `test-results/solver-ragdoll-settled.json`. The separate
105
+ `node scripts/check-ragdoll-net.mjs` regression checks every quarter-second
106
+ through 30 simulated seconds with automatic selection. It checks whole limbs
107
+ below the sheet and partial capsule/triangle intersections deeper than 5 mm.
108
+ The net uses overlapping plates and excludes its eight immediate neighbors
109
+ from self-collisions; distant folds still collide.
110
+
111
+ Tests compare unique, complete pair sets against the grid for empty and partial
112
+ treelets, duplicate keys, rotated hulls and boxes, spheres, giant statics,
113
+ ignored and released joints, filters, teleports and added bodies. Physical regressions cover floor support,
114
+ joints, sleeping and support removal; browser checks exercise motion and drawing.
115
+
116
+ `node scripts/check-hploc-motion.mjs` checks 360 steps of the 10K/50K mixed-size
117
+ scenes, 110K ring, 100K columns and half-million walls with the tree forced.
118
+ It checks every step's capacity and scheduling counters, measures floor support
119
+ and rotation, and captures four screenshots per scene. `npm run test:web`
120
+ includes this check alongside all scene and benchmark views.