File size: 3,131 Bytes
1829efb
 
 
fde700c
 
1829efb
fde700c
 
1829efb
fde700c
 
29664cd
fde700c
 
2c40bef
fde700c
 
 
 
 
 
 
 
 
 
 
29664cd
 
fde700c
1829efb
fde700c
 
1829efb
 
2c40bef
 
1829efb
 
 
 
 
 
 
 
 
 
 
 
 
 
7185739
31abac2
1829efb
31abac2
 
1829efb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ba04000
1829efb
 
 
 
 
 
 
 
 
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import worlds from 'virtual:worlds'
import { type World, type WorldEntry } from '../types/world'

export function getExternalWorld(): WorldEntry | undefined {
  if (typeof window === 'undefined') return undefined
  const params = new URLSearchParams(window.location.search)
  const modelUrl = params.get('model')
  if (!modelUrl) return undefined

  let finalUrl = modelUrl
  let displayName = 'External Model'

  if (modelUrl.startsWith('JYSM/')) {
    const hfId = modelUrl.slice(5)
    finalUrl = `https://huggingface.co/datasets/Junyueeeeee/SparkSplat_Model/resolve/main/${hfId}`
    if (!finalUrl.toLowerCase().endsWith('.ply') && !finalUrl.toLowerCase().endsWith('.spz')) {
      finalUrl += '.ply'
    }
    displayName = hfId
  } else {
    try {
      const url = new URL(modelUrl)
      const parts = url.pathname.split('/')
      const filename = parts[parts.length - 1]
      if (filename) displayName = decodeURIComponent(filename)
    } catch (e) {}
  }

  const isSpz = finalUrl.toLowerCase().endsWith('.spz')
  const world: World = {
    world_id: 'external-model',
    display_name: displayName,
    assets: {
      splats: {
        ply_url: isSpz ? undefined : `${finalUrl}${finalUrl.includes('?') ? '&' : '?'}nocache=${Date.now()}`,
        spz_urls: isSpz ? { full_res: `${finalUrl}${finalUrl.includes('?') ? '&' : '?'}nocache=${Date.now()}` } : {},
        semantics_metadata: { metric_scale_factor: 1, ground_plane_offset: 0, flip_y: true }
      },
      mesh: { collider_mesh_url: '' },
      imagery: { pano_url: '' },
      thumbnail_url: '',
      caption: ''
    },
    world_marble_url: '',
    tags: [],
    world_prompt: '',
    created_at: '',
    updated_at: ''
  }

  const dynamicSlug = `external-${displayName.replace(/[^a-zA-Z0-9_-]/g, '')}`

  return {
    slug: dynamicSlug,
    project: { slug: dynamicSlug, display_name: displayName },
    world,
    worldVersions: [{ index: 1, label: 'v1', complete: true, world }],
    objectAssets: [],
    allObjectAssets: [],
    sourceImageVersions: [],
    worldSfxUrls: []
  }
}

export function loadWorlds(): WorldEntry[] {
  const external = getExternalWorld()
  const local = worlds as WorldEntry[]
  return external ? [external, ...local] : local
}

export async function fetchWorlds(): Promise<WorldEntry[]> {
  const external = getExternalWorld()
  if (!import.meta.env.DEV) {
    const local = worlds as WorldEntry[]
    return external ? [external, ...local] : local
  }

  const response = await fetch('/__models', { cache: 'no-store' })
  if (!response.ok) throw new Error(await response.text())
  const fetched = await response.json() as WorldEntry[]
  return external ? [external, ...fetched] : fetched
}

function localWorldAssetUrl(url: string | undefined): string {
  if (!url) return ''
  return url.startsWith('http') || url.startsWith('/models/') || url.startsWith('blob:') ? url : ''
}

export function getSplatUrl(world: World): string {
  if (world.assets.splats.ply_url) {
    return localWorldAssetUrl(world.assets.splats.ply_url)
  }
  const urls = world.assets.splats.spz_urls
  return localWorldAssetUrl(urls.full_res)
}