Skip to content

Uniform decimation by default again; the adaptive path moves to --decimate-adaptive - #302

Merged
slimbuck merged 1 commit into
playcanvas:mainfrom
slimbuck:dec
Aug 10, 2026
Merged

Uniform decimation by default again; the adaptive path moves to --decimate-adaptive#302
slimbuck merged 1 commit into
playcanvas:mainfrom
slimbuck:dec

Conversation

@slimbuck

Copy link
Copy Markdown
Member

Swaps which decimator each flag names. #296 made the new adaptive path the default and parked the 3.1.x algorithm on --decimate-uniform; this restores --decimate to the pre-3.2 uniform decimator and gives the adaptive one its own flag. Neither algorithm changes — no file under src/lib/decimate/ or src/lib/decimate-uniform/ changes behaviour, and the two paths remain the ones documented in src/lib/decimate-uniform/README.md.

  • -d, --decimate — the frozen pre-3.2 decimator, removing at a uniform rate everywhere. The default.
  • --decimate-adaptive — the 3.2 adaptive decimator, allocating removal by local error.
  • --decimate-uniform is removed. Breaking for anyone who adopted it in 3.2.0; it now errors as an unknown option rather than silently changing meaning.

Library API

decimateSource / DecimateOptions / DecimateSpill now resolve to decimate-uniform/, and the adaptive path is exported as decimateSourceAdaptive / DecimateAdaptiveOptions / DecimateAdaptiveSpill. The decimate ProcessAction follows, so processDataTable runs the uniform path too; library callers wanting adaptive call decimateSourceAdaptive() directly, which mirrors how the CLI dispatches.

The renaming happens at each directory's index.ts, not inside it — the same aliasing trick decimate-uniform/index.ts already used, just pointed the other way. So decimate-uniform/'s bit-for-bit contract with the 3.1.6 binary is untouched: the only edit inside that directory is one comment in gpu-knn.ts, which is already a documented deviation. tools/decimate-parity.mjs and test/decimate-uniform-parity.test.mjs still guard it.

One behavioural consequence

The uniform decimator's stall guard is reachable through the default flag again: on a degenerate nearest-neighbour graph — many exactly-coincident splats — one-shot matching collapses onto the same few KNN hub points, a generation removes almost nothing, and it throws decimation stalled … refusing to grind toward the target. Re-costed selection re-derives candidates as clusters form and merges those scenes cleanly, so --decimate-adaptive still handles them.

This is 3.1.x behaviour returning with the 3.1.x algorithm, it needs a genuinely degenerate scene to trigger, and it fails loudly rather than returning a wrong count. It surfaced because test/decimate.test.mjs exercises the decimate action, whose 600-coincident-splats case asserted the adaptive result; that test now pins both halves — the action rejects, and decimateSourceAdaptive reaches the exact target — so neither behaviour loses coverage.

Verification

tsc --noEmit and eslint src clean; full suite 811/811. Both flags run end to end on test/fixtures/splat/minimal.splat and the progress log distinguishes them (Selecting merges vs Selecting merges (re-costed)).

Two follow-ups deliberately left out: no version bump, and scenes/DECIMATION-RESULTS.md needs no re-baseline but its old column is now what --decimate produces. tools/decimate-parity.mjs now compares the reference's --decimate against this tree's --decimate; a 3.2.x reference would need --decimate-uniform there, which the script's header notes.

@slimbuck
slimbuck requested a lite review from Copilot August 10, 2026 15:27
@slimbuck slimbuck self-assigned this Aug 10, 2026
@slimbuck slimbuck added the enhancement New feature or request label Aug 10, 2026

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.

Pull request overview

Restores the pre-3.2 uniform decimator as the default --decimate behavior (and as decimateSource() in the library API), while moving the newer adaptive decimator behind an explicit --decimate-adaptive flag (and decimateSourceAdaptive() export). This keeps both algorithms intact while swapping which names/flags refer to which path.

Changes:

  • CLI flag swap: --decimate now dispatches the uniform decimator; --decimate-adaptive dispatches the adaptive decimator; --decimate-uniform is removed.
  • Library API swap: decimateSource / DecimateOptions now resolve to decimate-uniform/, and the adaptive decimator is exported as decimateSourceAdaptive / DecimateAdaptiveOptions.
  • Tests + docs updated to cover and describe the new default/flag mapping, including parity tooling and degenerate-scene behavior expectations.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tools/decimate-parity.mjs Updates parity script to compare reference --decimate against this tree’s --decimate (uniform-by-default again).
test/decimate.test.mjs Splits coverage for the coincident-splats degenerate case: uniform action rejects; adaptive source path reaches target count.
test/decimate-uniform-parity.test.mjs Updates description to reflect uniform decimator is now reached via --decimate.
test/decimate-source.test.mjs Renames/retargets orchestrator tests to decimateSourceAdaptive.
test/decimate-multiblock.test.mjs Retargets multi-block adaptive-path tests to decimateSourceAdaptive.
test/cli.test.mjs Updates CLI test to use --decimate-adaptive for adaptive behavior.
src/lib/workers/tasks.ts Updates comments to reflect uniform path is now --decimate.
src/lib/process.ts Switches decimate ProcessAction implementation to use the uniform decimator; updates doc comment accordingly.
src/lib/index.ts Swaps public exports: decimateSource now from decimate-uniform, and adaptive exported as decimateSourceAdaptive with renamed option/spill types.
src/lib/decimate/priority.ts Updates comments referencing which CLI flag corresponds to the uniform full-SH scoring path.
src/lib/decimate/index.ts Re-exports adaptive decimator under decimateSourceAdaptive (and option/spill types under DecimateAdaptive*) without renaming internals.
src/lib/decimate/decimate-source.ts Updates adaptive multi-block WebGPU error message to suggest --decimate as the uniform fallback.
src/lib/decimate-uniform/README.md Updates documentation to reflect uniform decimator is default again (--decimate / decimateSource).
src/lib/decimate-uniform/index.ts Removes the *Uniform alias exports; uniform decimator is now the canonical decimateSource export here.
src/lib/decimate-uniform/gpu-knn.ts Updates comments to reflect uniform path is now --decimate.
src/cli/index.ts Implements new CLI option name --decimate-adaptive and updates dispatch to call adaptive vs uniform accordingly.
README.md Updates CLI usage docs to reflect --decimate (uniform default) vs --decimate-adaptive (adaptive).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@slimbuck
slimbuck marked this pull request as ready for review August 10, 2026 15:39
@slimbuck
slimbuck requested a review from a team August 10, 2026 15:39
@slimbuck
slimbuck merged commit f4c5687 into playcanvas:main Aug 10, 2026
3 checks passed
@slimbuck
slimbuck deleted the dec branch August 10, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants