All files / src/components/VirtualWalkthrough splatFormat.ts

100% Statements 16/16
100% Branches 8/8
100% Functions 2/2
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58                                        1x                           1x   4x   1x 12x 12x   12x 3x   9x 4x   5x 1x   4x 2x     2x    
/*
 * The playcanvas gsplat loader picks its parser from the asset's `filename`, not from the URL it
 * actually downloads, because a splat is frequently served from a signed or extensionless URL. Each
 * supported format therefore maps to a canonical filename whose extension/basename routes the asset
 * to the matching engine parser:
 *
 *   model.sog     -> SogBundleParser      sog packed into a single zip archive
 *   meta.json     -> SogParser            the same sog data left unpacked as separate files
 *   lod-meta.json -> GSplatOctreeParser   sog with LOD levels, streamed in as the camera moves
 *   model.ply     -> PlyParser
 *
 * `sog` and `sogUnbundled` are two packagings of one format, not two formats: both parsers build a
 * GSplatSogData/GSplatSogResource and both await every texture before the resource exists. Only
 * `sogStreamed` streams — playcanvas.d.ts on GSplatOctreeResource#numSplats: "Not all of these are
 * resident at runtime: the LOD streaming system selects a subset per node based on view distance and
 * the configured splat budget."
 *
 * Only the filename is faked; the textures an unbundled or streamed sog references are still
 * resolved relative to the real URL, so no rewriting of splatSrc is needed.
 */
const LOADER_FILENAMES = {
  sog: 'model.sog',
  sogUnbundled: 'meta.json',
  sogStreamed: 'lod-meta.json',
  ply: 'model.ply',
} as const;
 
export type SplatFormat = keyof typeof LOADER_FILENAMES;
 
/**
 * Format assumed when a URL is too opaque to tell us anything. Kept as the bundled `.sog` archive so
 * that existing extensionless splat URLs keep loading the way they did before the other formats were
 * supported.
 */
export const DEFAULT_SPLAT_FORMAT: SplatFormat = 'sog';
 
export const splatLoaderFilename = (format: SplatFormat): string => LOADER_FILENAMES[format];
 
export const detectSplatFormat = (splatSrc: string): SplatFormat => {
  const path = splatSrc.split(/[?#]/)[0];
  const basename = path.slice(path.lastIndexOf('/') + 1).toLowerCase();
 
  if (basename === 'lod-meta.json') {
    return 'sogStreamed';
  }
  if (basename === 'meta.json') {
    return 'sogUnbundled';
  }
  if (basename.endsWith('.ply')) {
    return 'ply';
  }
  if (basename.endsWith('.sog')) {
    return 'sog';
  }
 
  return DEFAULT_SPLAT_FORMAT;
};