From dbff1ab9c098422d08fc31ee94f26b9c67757f59 Mon Sep 17 00:00:00 2001 From: Johnathan Chiu Date: Tue, 15 Sep 2026 09:40:33 +0800 Subject: [PATCH 1/2] feat(capture): render generated SpaceForm scenes --- packages/capture-protocol/src/schema.ts | 1 + packages/capture-viewer/src/capture-runtime.tsx | 2 +- packages/capture-viewer/src/stream-rendering.ts | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/capture-protocol/src/schema.ts b/packages/capture-protocol/src/schema.ts index 012e7b5fa2..54eb095247 100644 --- a/packages/capture-protocol/src/schema.ts +++ b/packages/capture-protocol/src/schema.ts @@ -307,6 +307,7 @@ export function captureLayerKey(stream: CaptureStreamDescriptor): string { if (stream.kind === 'point-cloud') return 'pointCloud' if (stream.kind === 'surface-mesh') return 'surfaceMesh' if (stream.kind === 'gaussian-splat') return 'splat' + if (stream.kind === 'spaceform-scene') return 'spaceformScene' return stream.kind } diff --git a/packages/capture-viewer/src/capture-runtime.tsx b/packages/capture-viewer/src/capture-runtime.tsx index 31cb22c909..0d6303314c 100644 --- a/packages/capture-viewer/src/capture-runtime.tsx +++ b/packages/capture-viewer/src/capture-runtime.tsx @@ -311,7 +311,7 @@ export function CaptureStreamLayer({ /> ) } else if ( - layerKey === 'model' && + (layerKey === 'model' || layerKey === 'spaceformScene') && isCaptureModelArtifact(stream.artifact) && stream.artifact && artifactUrl diff --git a/packages/capture-viewer/src/stream-rendering.ts b/packages/capture-viewer/src/stream-rendering.ts index 2fcfea7aeb..3a024be7bd 100644 --- a/packages/capture-viewer/src/stream-rendering.ts +++ b/packages/capture-viewer/src/stream-rendering.ts @@ -21,7 +21,9 @@ export function isCaptureStreamRenderable( if (stream.availability === 'failed' || stream.availability === 'pending') return false const layerKey = captureLayerKey(stream) if (customRendererKeys.has(layerKey) || customRendererKeys.has(stream.kind)) return true - if (layerKey === 'model') return isCaptureModelArtifact(stream.artifact) + if (layerKey === 'model' || layerKey === 'spaceformScene') { + return isCaptureModelArtifact(stream.artifact) + } if (layerKey === 'deviceMotion') { return ( stream.availability === 'live' || From 3124122f7622f93c490d06ddcd7f5d4c4ca62e09 Mon Sep 17 00:00:00 2001 From: Aymeric Rabot Date: Thu, 17 Sep 2026 15:32:37 -0400 Subject: [PATCH 2/2] test(capture): preserve independent generated scene layers --- packages/core/src/capture/schema.test.ts | 12 ++++++++++++ .../src/capture/stream-rendering.test.ts | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/packages/core/src/capture/schema.test.ts b/packages/core/src/capture/schema.test.ts index 3dbb6e8c7a..f3fb5e8e63 100644 --- a/packages/core/src/capture/schema.test.ts +++ b/packages/core/src/capture/schema.test.ts @@ -8,6 +8,18 @@ import { const identity = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] describe('capture manifests', () => { + test('keeps generated scenes independent from the original room model', () => { + const descriptor = normalizeCaptureSessionManifest({ + schemaVersion: 2, + sessionId: 'capture_123', + streams: [ + { id: 'room', kind: 'room-model', role: 'model' }, + { id: 'generated', kind: 'spaceform-scene' }, + ], + }) + expect(descriptor.streams.map(captureLayerKey)).toEqual(['model', 'spaceformScene']) + }) + test('normalizes the Community v1 manifest into extensible streams', () => { const descriptor = normalizeCaptureSessionManifest({ schemaVersion: 1, diff --git a/packages/viewer/src/capture/stream-rendering.test.ts b/packages/viewer/src/capture/stream-rendering.test.ts index 857777c38e..be0535f2d1 100644 --- a/packages/viewer/src/capture/stream-rendering.test.ts +++ b/packages/viewer/src/capture/stream-rendering.test.ts @@ -2,6 +2,25 @@ import { describe, expect, test } from 'bun:test' import { isCaptureStreamRenderable } from './stream-rendering' describe('isCaptureStreamRenderable', () => { + test('renders completed generated models while withholding failed and pending results', () => { + const stream = { + id: 'generated', + kind: 'spaceform-scene', + artifact: { id: 'generated', mediaType: 'model/gltf-binary', uri: '/scene.glb' }, + } + expect(isCaptureStreamRenderable({ ...stream, availability: 'ready' })).toBe(true) + for (const availability of ['pending', 'failed'] as const) { + expect(isCaptureStreamRenderable({ ...stream, availability })).toBe(false) + } + expect(isCaptureStreamRenderable({ id: stream.id, kind: stream.kind })).toBe(false) + expect( + isCaptureStreamRenderable({ + ...stream, + artifact: { id: 'unsupported', mediaType: 'application/json', uri: '/scene.json' }, + }), + ).toBe(false) + }) + test('only advertises point-cloud formats handled by the reference renderer', () => { expect( isCaptureStreamRenderable({