Repository navigation
Fit the LOD chunk extent to a chunk count target - #335
mvaligursky wants to merge 3 commits into
Conversation
Adds --lod-max-chunks (default 5000): when the partition at --lod-chunk-extent would produce more chunks, the extent is raised until it fits. A viewer evaluates every chunk on each LOD update, and large dense scenes cut at the default extent reached tens of thousands of chunks (31,667 for a 212M splat capture, now 4,968 at a 131 m extent). Small scenes keep the requested extent. The extent used and the target are recorded in lod-meta.json. Lowers the --lod-chunk-min default from 8 to 1, so sparse regions split into reasonably sized chunks instead of one wide chunk, which a viewer can cull and choose detail for more precisely.
mvaligursky
left a comment
There was a problem hiding this comment.
Automated PR review by Codex (OpenAI AI agent) of commit 153d712. Two actionable findings are inline. Focused LOD writer tests: 33 passed, 9 GPU-dependent tests skipped; changed-file lint and PR Build/Docs/Lint checks passed. The broader local suite was not a valid gate here because it needs a fresh dist build, GPU support, and local HTTP fixtures.
|
|
||
| let lo = minExtent; | ||
| while (hi > lo * 1.01) { | ||
| const mid = Math.sqrt(lo * hi); |
There was a problem hiding this comment.
[P2] --lod-chunk-extent 0 is accepted by the CLI and previously meant split down to the spatial-tree floor, but with a positive --lod-max-chunks this loop can never advance: lo is 0, so sqrt(lo * hi) stays 0 and hi > lo * 1.01 remains true. I reproduced an indefinitely running chooseChunkExtent with a 4096-point line, extent 0 and target 4. Please validate a strictly positive extent for the fitter or use a midpoint/termination rule that handles zero (and reject negative extents explicitly).
There was a problem hiding this comment.
Fixed in c591be9. While the lower bound is 0 the fit halves the upper bound, and switches to the geometric midpoint once it has a non-zero lower bound; an iteration cap guards trees whose nodes have no width. A negative extent is treated as 0 by the library, and the CLI now rejects negative --lod-chunk-extent and --lod-max-chunks values. Covered by tests for a requested extent of 0 (target 4 on a 4,096-point line) and a negative extent.
| } | ||
|
|
||
| let hi = Math.max(minExtent, root.aabb.largestDim()); | ||
| if (countLeaves(root, binSize, hi, binMin) > maxChunks) { |
There was a problem hiding this comment.
[P2] When file-unit splits alone exceed maxChunks, raising the extent cannot meet the target, but this branch silently returns the full width. The added test demonstrates target 2 yielding 8 leaves; the writer then logs that the extent was raised to fit 2 chunks and records asset.maxChunks: 2, while the viewer still evaluates 8. This can happen with a small --lod-chunk-count on ordinary scenes. Please surface an unmet-target warning/error (or adjust the file-unit size) and avoid claiming the bound was met.
There was a problem hiding this comment.
Going over is by design: --lod-max-chunks is a target, and --lod-chunk-count takes precedence, so a scene whose Gaussian count alone requires more chunks keeps them. The reporting was misleading though, fixed in c591be9: in that case the log now reads e.g. "LOD chunk extent raised to 26744.0m: 16 chunks, above the --lod-max-chunks target of 4 (--lod-chunk-count splits require more)", and the option, manifest field, CLI help and README describe it as a target that --lod-chunk-count can override.
… a target The extent fit bisected geometrically from the requested extent, so a requested extent of 0 never advanced. It now halves the upper bound until it has a non-zero lower bound, with an iteration cap for degenerate trees. The CLI rejects negative --lod-chunk-extent and --lod-max-chunks values. --lod-max-chunks is a target: --lod-chunk-count splits take precedence, so a scene whose Gaussian count alone requires more chunks keeps them. The log no longer reports such a result as fitting the target, and the docs say so.
mvaligursky
left a comment
There was a problem hiding this comment.
Automated PR re-review by Codex (OpenAI AI agent), on c591be9. The zero-extent nontermination is fixed, and the target/precedence semantics are now documented. I found one remaining reporting gap below. Focused LOD tests: 35 passed, 9 GPU-dependent skipped; changed-file lint and PR CI checks passed.
| const binDim = chunkExtent; | ||
| const binMin = chunkMin * 1024; | ||
| const binDim = chooseChunkExtent(bTree.root, binSize, binMin, chunkExtent, maxChunks); | ||
| if (binDim > chunkExtent) { |
There was a problem hiding this comment.
[P2] Report an unmet chunk target even when the extent does not rise. This branch only counts/logs leaves when binDim > chunkExtent, but file-unit splits can exceed maxChunks while the requested extent already spans the scene. I reproduced 4,096 Gaussians within 1 m with chunkCount=1, chunkExtent=16, and maxChunks=2: chooseChunkExtent returns 16, the partition has 4 leaves, and this new diagnostic is skipped entirely. Please check the final leaf count independently of whether the extent changed, so this case also tells users that the target was missed.
The chunk target report only ran when the extent limit was raised, so a scene whose file-unit splits exceeded --lod-max-chunks while the requested extent already spanned it was silent. The report now follows the final chunk count: a missed target is reported whatever the extent did, a met target is reported when the extent was raised, and nothing is reported when the target is off, including for a negative requested extent. When file units alone exceed the target, the fit aims for the fewest chunks the tree can reach, at the smallest extent reaching them, instead of returning the full width - the same partition, but a meaningful recorded extent.
Large dense scenes cut at the default LOD chunk extent produce tens of thousands of chunks, and a viewer evaluates every chunk on each LOD update. This adds a chunk count target: when the partition would hold more chunks, the extent is raised until it fits. Small scenes keep the requested extent.
Changes:
--lod-max-chunks <n>(default 5000, 0 disables): a target number of chunks. The chunk extent starts at--lod-chunk-extentand is raised to the smallest value at which the tree holds at most this many chunks.--lod-chunk-counttakes precedence, so a scene whose Gaussian count alone requires more chunks keeps them, and the log says so. The search walks only the spatial tree's counts and bounds, a few milliseconds even for 200M+ splats.--lod-chunk-mindefault lowered from 8 to 1, so sparse regions split into reasonably sized chunks instead of one wide chunk, which a viewer can cull and choose detail for more precisely.lod-meta.jsonrecords the extent used (asset.chunkExtent) and the target (asset.maxChunks).--lod-chunk-extentand--lod-max-chunksreject negative values.Results (chunks, before -> after):
API Changes:
--lod-max-chunks, library optionWriteLodSourceOptions.maxChunks/lodMaxChunks.--lod-chunk-min/chunkMindefault changed from 8 to 1.asset.maxChunks.