From 07dd314e47c8169162735316c87d84437e9cba8a Mon Sep 17 00:00:00 2001 From: jesus luque Date: Tue, 6 Oct 2026 03:39:02 +0200 Subject: [PATCH 1/2] Fix SplatAccumulator: packed covSplats threw "Generator must be provided" With covSplats and without extSplats, a stray check after the packed covariance branch required a GsplatGenerator, so a covGenerator alone (which that branch already handles) always threw. Remove it. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01JtbHkmUpoNeo1EwbHiLihG --- src/SplatAccumulator.ts | 3 --- test/unit/SplatAccumulator.test.ts | 29 +++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 test/unit/SplatAccumulator.test.ts diff --git a/src/SplatAccumulator.ts b/src/SplatAccumulator.ts index 5ca9fc23..44388c0f 100644 --- a/src/SplatAccumulator.ts +++ b/src/SplatAccumulator.ts @@ -309,9 +309,6 @@ export class SplatAccumulator { ); roots.push(output); } - if (!generator) { - throw new Error("Generator must be provided"); - } } if (generator) { const outputDepth = outputSplatDepth( diff --git a/test/unit/SplatAccumulator.test.ts b/test/unit/SplatAccumulator.test.ts new file mode 100644 index 00000000..1f99f81f --- /dev/null +++ b/test/unit/SplatAccumulator.test.ts @@ -0,0 +1,29 @@ +import { expect, test } from "vitest"; +import { SplatAccumulator } from "../../src/SplatAccumulator"; +import type { CovSplatGenerator } from "../../src/SplatGenerator"; +import { Dyno, dynoBlock } from "../../src/dyno/base"; +import { CovSplat } from "../../src/dyno/splats"; + +function covGenerator(): CovSplatGenerator { + return dynoBlock({ index: "int" }, { covsplat: CovSplat }, () => ({ + covsplat: new Dyno({ + outTypes: { covsplat: CovSplat }, + statements: ({ outputs }) => [ + `${outputs.covsplat}.flags = GSPLAT_FLAG_ACTIVE;`, + ], + }).outputs.covsplat, + })); +} + +// The packed covariance accumulator (covSplats without extSplats) builds its +// program from a covGenerator alone, as the extended one does. +test("packed covSplats accumulator accepts a covGenerator alone", () => { + for (const extSplats of [false, true]) { + const accumulator = new SplatAccumulator({ extSplats, covSplats: true }); + const { program } = accumulator.prepareProgramMaterial( + undefined, + covGenerator(), + ); + expect(program).toBeTruthy(); + } +}); From fcd9e4fa666cc0ca318894dd920b8446cbfdc144 Mon Sep 17 00:00:00 2001 From: Oscar Lorentzon Date: Sun, 18 Oct 2026 17:48:55 -0700 Subject: [PATCH 2/2] Split the covariance accumulator test by mode The test ran the packed and the extended accumulator inside one case named after the packed one. Each mode is now its own case, and the generator declares only its input and output types. --- test/unit/SplatAccumulator.test.ts | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/test/unit/SplatAccumulator.test.ts b/test/unit/SplatAccumulator.test.ts index 1f99f81f..861cce2f 100644 --- a/test/unit/SplatAccumulator.test.ts +++ b/test/unit/SplatAccumulator.test.ts @@ -1,29 +1,21 @@ import { expect, test } from "vitest"; import { SplatAccumulator } from "../../src/SplatAccumulator"; import type { CovSplatGenerator } from "../../src/SplatGenerator"; -import { Dyno, dynoBlock } from "../../src/dyno/base"; +import { dynoBlock } from "../../src/dyno/base"; import { CovSplat } from "../../src/dyno/splats"; function covGenerator(): CovSplatGenerator { - return dynoBlock({ index: "int" }, { covsplat: CovSplat }, () => ({ - covsplat: new Dyno({ - outTypes: { covsplat: CovSplat }, - statements: ({ outputs }) => [ - `${outputs.covsplat}.flags = GSPLAT_FLAG_ACTIVE;`, - ], - }).outputs.covsplat, - })); + return dynoBlock({ index: "int" }, { covsplat: CovSplat }, () => ({})); } -// The packed covariance accumulator (covSplats without extSplats) builds its -// program from a covGenerator alone, as the extended one does. -test("packed covSplats accumulator accepts a covGenerator alone", () => { - for (const extSplats of [false, true]) { +test.each([false, true])( + "covSplats accumulator with extSplats %s builds a program for a covSplats mesh", + (extSplats) => { const accumulator = new SplatAccumulator({ extSplats, covSplats: true }); const { program } = accumulator.prepareProgramMaterial( undefined, covGenerator(), ); expect(program).toBeTruthy(); - } -}); + }, +);