Skip to content

Support tiled voxel collision output for large scenes - #345

Open
Shuang-su wants to merge 2 commits into
playcanvas:mainfrom
Shuang-su:feat/voxel-tiles
Open

Shuang-su wants to merge 2 commits into
playcanvas:mainfrom
Shuang-su:feat/voxel-tiles

Conversation

@Shuang-su

@Shuang-su Shuang-su commented Oct 2, 2026 •

Copy link
Copy Markdown

This contribution adds an end-to-end tiled voxel workflow for large scenes: generating collision data one spatial tile at a time, then streaming nearby tiles in the viewer for collision-aware walking and debug visualization. Per-tile processing bounds the Gaussian upload size, while neighborhood loading limits the viewer's active collision working set.

This PR implements the generation half; supersplat-viewer #328 implements streaming, collision-aware walking and debug preview. Related discussions: #344, #343 and #253.

Public fixture and exact commands · Validation and screenshots

Problem, change and verified result

Result
Existing failure In #343, a 148,571,989-Gaussian scene requests one 9,508,607,296-byte upload buffer (about 9.51 GB), exceeding the device limit.
New path Opt-in tiled output gathers and uploads one bounded tile, writes standard voxel 1.1 files, then publishes a relative-URL manifest.
Verified integration The 2,220-Gaussian fixture generates six tiles; the viewer initially loads four nearby tiles and walks across the seam into a blocking wall on both WebGPU and WebGL2.

The default per-tile budget is 4,000,000 selected Gaussians. At 64 bytes per Gaussian, this bounds the Gaussian upload buffer to 256,000,000 bytes (256 MB, about 244 MiB), reduced further by the device's buffer and storage-binding limits. This is a code-derived bound for one Gaussian buffer, not measured total CPU/GPU memory or peak process RSS. Tiles exceeding their budget fail with guidance to reduce tile size or overlap.

The 149M-Gaussian scene from splat-transform #343 has not been rerun with this implementation. The existing monolithic writer is unchanged. No whole-scene peak-memory reduction, conversion-speed improvement or exhaustive large-scene walking validation is claimed.

Implemented

  • CLI tile size / overlap options (64 / 8 world units by default), library API and documentation; existing voxel resolution and opacity options are reused.
  • One source bounds pass and repeated chunk scans per tile, reading only position/geometric layers. Pending transforms are applied to world coordinates, and tile selection uses Gaussian extents rather than centers alone.
  • A common four-voxel block lattice and a private cleanup guard, with zero-overlap seam comparisons against monolithic output.
  • Capacity checks before upload, actionable budget errors, and tile resource cleanup on failures.
  • Nonempty standard tile files, followed by the manifest only after all tiles succeed. Empty output is distinct from failed generation.
  • A synthetic floor/wall generator and CPU/WebGPU regression tests requiring no private capture.

Reproduce

From this PR's checkout, use Node 24 and a WebGPU-capable adapter. Use a fresh generated directory:

npm ci
npm run build
mkdir -p generated
node bin/cli.mjs generators/gen-voxel-tiles.mjs generated/scene.ply
node bin/cli.mjs generators/gen-voxel-tiles.mjs generated/scene.voxel-tiles.json \
  --voxel-size 0.1 --voxel-tile-size 4 --voxel-tile-overlap 0.4
node bin/cli.mjs generators/gen-voxel-tiles.mjs generated/single.voxel.json --voxel-size 0.1
TEST_WEBGPU=1 node --import tsx --test --test-force-exit test/voxel-tiles.test.mjs

Expected: six manifest entries, each resolving to a nonempty voxel JSON/bin pair. The single asset is the comparison output; the test checks decoded occupancy. For walking and visualization, follow the companion viewer's direct preview steps.

Validation

Revalidated on 10 October 2026, after merging official main 4593166 (3.10.1) into this branch. On Node 24.21.0, a fresh npm ci and npm test passed (875 passed, 1 skipped); explicit tiled CPU/WebGPU tests passed 12/12 with the updated webgpu 0.6.2 / PlayCanvas 2.23.1 dependencies. Formatting, lint, typecheck, publint and Typedoc also passed. Typedoc reported 13 pre-existing warnings and publint an existing metadata suggestion. Tests cover core occupancy compared with monolithic output, a rotated cross-boundary Gaussian, zero-overlap seams, grid alignment, transforms, empty tiles/gaps, capacity failures, failed reads and failed output writes.

The CLI fixture was regenerated on 10 October 2026: 2,220 Gaussians and six populated tiles, with every relative JSON/bin URL resolving to a nonempty file. The viewer's actual collision classes loaded these files over localhost HTTP: four nearby tiles initially, deduplicated requests, neighborhood switching, floor queries on both sides of the X seam, and wall ray/capsule responses matching the regenerated monolithic output. Outside coverage was blocked and destruction cleared active colliders. This recheck used Node collision integration; it did not rerun browser rendering or visual walking.

In the 2 October 2026 Chrome integration, the public 2,220-Gaussian floor/wall fixture generated six populated tiles. At the initial camera position, the viewer requested four nearby tiles, leaving the other two unrequested until needed. In Chrome, WebGPU and WebGL2 both walked across the tile seam and stopped against the wall. WebGPU overlay and heatmap rendered; the single-voxel comparison also rendered and collided.

Draft scope and review questions

  • Surface voxelization only: global external fill, floor fill, carve and collision-mesh export are explicitly rejected.
  • Repeated scans trade throughput for bounded output-stage geometry residency; eager decoders and prior whole-scene actions can still retain scene data.
  • No automatic subdivision, resume or transactional in-place replacement. Failed runs can leave unreferenced tile files.
  • Please review the proposed v1 manifest, naming, default budget and surface-only scope. The viewer's debug overlay independently composites tiles, with documented overlap-brightness and cross-tile occlusion limitations.

Historical application background

Dayun (293 entries) and Bijiashan (320 entries) motivated this contribution. They are historical MetaFlow builds with a coordinate adapter, not this upstream build. Deployment evidence records empty-entry 404s, resource errors and unvalidated walking from the tested elevated viewpoints. No original full capture is uploaded.

Hosted check status

The latest upstream GitHub Actions run currently reports action_required with no jobs run, pending maintainer approval. The results above are completed local Node 24 checks; hosted CI has not passed yet.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants