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/core/src/capture/schema.ts b/packages/core/src/capture/schema.ts index 012e7b5fa2..54eb095247 100644 --- a/packages/core/src/capture/schema.ts +++ b/packages/core/src/capture/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/viewer/src/capture/capture-runtime.tsx b/packages/viewer/src/capture/capture-runtime.tsx index c5efb7b194..0919145d02 100644 --- a/packages/viewer/src/capture/capture-runtime.tsx +++ b/packages/viewer/src/capture/capture-runtime.tsx @@ -313,7 +313,7 @@ export function CaptureStreamLayer({ /> ) } else if ( - layerKey === 'model' && + (layerKey === 'model' || layerKey === 'spaceformScene') && isCaptureModelArtifact(stream.artifact) && stream.artifact && artifactUrl 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({ diff --git a/packages/viewer/src/capture/stream-rendering.ts b/packages/viewer/src/capture/stream-rendering.ts index 663ccd6ce8..065d1fcf60 100644 --- a/packages/viewer/src/capture/stream-rendering.ts +++ b/packages/viewer/src/capture/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' ||