cosmo/frontend/ASSET_LOADING_ANALYSIS.md

12 KiB

Cosmo Frontend Asset Loading Strategy Analysis

Executive Summary

The Cosmo frontend project implements a 3D solar system visualization using Three.js and React-Three-Fiber. The asset loading strategy currently uses a mix of on-demand fetching and preloading patterns, with assets served through a backend API proxy.


1. Asset Inventory

1.1 Texture Assets (Primary Location: Backend Upload)

Backend Location: /Users/jiliu/WorkSpace/cosmo/backend/upload/texture/

  • Total Size: ~19 MB
  • Format: Primarily JPEG with some PNG
  • Built/Dist Location: /Users/jiliu/WorkSpace/cosmo/frontend/dist/textures/

Key Texture Files (by size):

File Size Purpose
2k_moon.jpg 1.0 MB Moon surface texture
2k_venus_surface.jpg 868 KB Venus surface
2k_mercury.jpg 856 KB Mercury surface
2k_sun.jpg 804 KB Sun/Star texture
2k_mars.jpg 736 KB Mars surface
2k_jupiter.jpg 488 KB Jupiter surface
2k_earth_daymap.jpg 456 KB Earth day side
2k_earth_nightmap.jpg 256 KB Earth night side
2k_stars_milky_way.jpg 248 KB Milky Way background
2k_neptune.jpg 236 KB Neptune surface
2k_venus_atmosphere.jpg 228 KB Venus atmosphere
2k_saturn.jpg 196 KB Saturn surface
2k_uranus.jpg 76 KB Uranus surface
2k_saturn_ring_alpha.png 12 KB Saturn ring transparency

Additional Textures (comets, dwarf planets, moons):

  • 2k_pluto.jpg: 3.8 MB (largest single file)
  • Various comet/asteroid textures: 300-500 KB each
  • Moon textures (Ganymede, Io, Titan, Mimas): 350-360 KB each

1.2 3D Model Assets (GLB/GLTF Format)

Backend Location: /Users/jiliu/WorkSpace/cosmo/backend/upload/model/

  • Total Size: ~24 MB
  • Format: GLB (binary GLTF)

Key Model Files (by size):

File Size Purpose
juno.glb 8.6 MB Juno space probe
cassini.glb 1.6 MB Cassini spacecraft
voyager_2.glb 1.6 MB Voyager 2 probe
parker_solar_probe.glb 436 KB Parker Solar Probe
voyager_1.glb 280 KB Voyager 1 probe
webb_space_telescope.glb ~1-2 MB (from list) JWST
new_horizons.glb ~1-2 MB (from list) New Horizons probe
perseverance.glb ~1-2 MB (from list) Mars Perseverance rover

Observations:

  • Juno.glb (8.6 MB) is significantly larger than other models
  • Most probes range 280 KB to 1.6 MB
  • Total probe models: ~24 MB for ~8 spacecraft

2. Asset Loading Strategy

2.1 Texture Loading (Detailed Implementation)

File: /Users/jiliu/WorkSpace/cosmo/frontend/src/components/CelestialBody.tsx

// Current Loading Pattern:
1. Component mounts (Planet component)
2. fetchBodyResources(body.id, 'texture') - calls API
3. Finds main texture (excludes 'atmosphere' and 'night')
4. Constructs URL: /upload/{file_path}
5. useTexture(texturePath) - Three.js texture loader
6. Renders mesh with loaded texture

// Key Line:
const texture = texturePath ? useTexture(texturePath) : null;

Loading Characteristics:

  • Type: On-demand (per celestial body)
  • Caching: useTexture hook likely caches within session
  • Error Handling: Falls back to null (gray placeholder material)
  • Performance: No preloading - each body texture loads when component mounts

2.2 Model Loading (3D Probes)

File: /Users/jiliu/WorkSpace/cosmo/frontend/src/components/Probe.tsx

// Current Loading Pattern:
1. Component mounts (Probe component)
2. fetchBodyResources(body.id, 'model') - calls API
3. Gets first model resource + scale metadata
4. Constructs URL: /upload/{file_path}
5. useGLTF.preload(fullPath) - PRELOADING ENABLED
6. setModelPath(fullPath)
7. useGLTF(modelPath) - loads and parses GLB

// Key Implementation:
useGLTF.preload(fullPath);  // Preload before rendering
const gltf = useGLTF(modelPath);  // Actual load

Loading Characteristics:

  • Type: On-demand with optional preloading
  • Preloading: Yes - useGLTF.preload() is called (Line 281)
  • Caching: useGLTF hook caches in session
  • Scale Handling: Custom scale from extra_data.scale
  • Fallback: ProbeFallback component renders red sphere if load fails
  • Performance: Preload triggered immediately, improves perceived load time

2.3 Background/Static Assets

File: /Users/jiliu/WorkSpace/cosmo/frontend/src/components/Scene.tsx

// Procedural Assets (NO external files):
1. BackgroundStars (radius=300, count=5000, procedural)
2. AsteroidBelts (procedurally generated)
3. Nebulae (procedurally generated)
4. Constellations (data-driven but rendered procedurally)

// Data-Driven Assets (fetched from API):
1. Stars (real star catalog data)
2. Galaxies (CanvasTexture generated)
3. Satellites/Planets (textures fetched on demand)

Observations:

  • Extensive use of procedural generation reduces asset file count
  • Galaxy textures created with CanvasTexture (no disk files)
  • Star data loaded from API, rendered with simple geometry

3. Loading Flow & Architecture

3.1 Request Path

Frontend Component
    ↓
fetchBodyResources(bodyId, type)
    ↓
API Call: /api/celestial/resources/{bodyId}?resource_type=texture|model
    ↓
Backend API (Port 8000)
    ↓
Vite Proxy Dev: localhost:8000/upload/{type}/{filename}
OR
Nginx Production: proxy to backend
    ↓
Actual File: /backend/upload/{type}/{filename}
    ↓
Response to Frontend
    ↓
useTexture() or useGLTF()
    ↓
Three.js Renderer

3.2 API Integration Points

File: /Users/jiliu/WorkSpace/cosmo/frontend/src/utils/api.ts

// Fetch function signature:
export async function fetchBodyResources(
  bodyId: string,
  resourceType?: string
): Promise<{
  body_id: string;
  resources: Array<{
    id: number;
    resource_type: string;
    file_path: string;      // e.g., "texture/2k_sun.jpg"
    file_size: number;
    mime_type: string;
    created_at: string;
    extra_data?: Record<string, any>;  // scale, etc.
  }>;
}>

4. Vite Build Configuration

File: /Users/jiliu/WorkSpace/cosmo/frontend/vite.config.ts

export default defineConfig({
  plugins: [react()],
  server: {
    host: '0.0.0.0',
    port: 5173,
    proxy: {
      '/api': {
        target: 'http://localhost:8000',
        changeOrigin: true,
      },
      '/upload': {
        target: 'http://localhost:8000',
        changeOrigin: true,
      },
      '/public': {
        target: 'http://localhost:8000',
        changeOrigin: true,
      },
    },
  },
})

Current Configuration Analysis:

  • No explicit asset optimization: No image compression, no WebP conversion
  • No size limits: All assets proxied without size constraints
  • No chunking strategy: Vite default chunks (1.2 MB JS bundle observed)
  • Proxy strategy: All assets proxied through backend (good for dynamic content)

5. Build Output Analysis

Dist Directory: /Users/jiliu/WorkSpace/cosmo/frontend/dist/

  • Total Size: ~20 MB
  • JavaScript Bundle: 1.2 MB (index-c2PfKiPB.js)
  • CSS: 9.8 KB
  • Textures: ~7.9 MB (in dist, smaller than backend copy)
  • Models: ~12.8 MB (in dist)

Key Finding: Textures in dist folder are smaller than backend source, suggesting some optimization (JPEG compression) during build/deploy.


6. Lazy Loading & Code Splitting

File: /Users/jiliu/WorkSpace/cosmo/frontend/src/App.tsx

// Already Implemented:
const InterstellarTicker = lazy(() => 
  import('./components/InterstellarTicker')
    .then(m => ({ default: m.InterstellarTicker }))
);

const MessageBoard = lazy(() => 
  import('./components/MessageBoard')
    .then(m => ({ default: m.MessageBoard }))
);

const BodyDetailOverlay = lazy(() => 
  import('./components/BodyDetailOverlay')
    .then(m => ({ default: m.BodyDetailOverlay }))
);

// Wrapped in Suspense:
<Suspense fallback={null}>
  <InterstellarTicker />
</Suspense>

Status:

  • Lazy loading implemented for 3 non-critical components
  • Suspense fallback set to null (no skeleton loading)
  • No lazy loading for 3D rendering components (CelestialBody, Probe, Scene)

7. Current Optimization Opportunities

7.1 Identified Issues

  1. No Texture Compression

    • Total texture size: 19 MB (backend) → 7.9 MB (dist)
    • JPEG quality likely could be reduced further
    • No WebP fallback for modern browsers
    • No LOD (Level of Detail) system
  2. Large Model File

    • Juno.glb: 8.6 MB (30% of all model assets)
    • No model optimization/decimation
    • No LOD for probes
    • All vertices/triangles loaded even when zoomed out
  3. No Batch Asset Loading

    • Each body texture loaded individually
    • 10+ API calls for visible celestial bodies
    • No batching or parallel loading optimization
    • No request deduplication
  4. All-or-Nothing Texture Loading

    • Texture loading blocks render until complete
    • Falls back to gray if load fails
    • No progressive/streaming load
  5. Limited Caching Strategy

    • useTexture/useGLTF cache only within session
    • No persistent browser cache headers optimization
    • No service worker caching
  6. Background Star Data

    • Stars component loads 1000+ star systems per API call
    • No pagination or frustum culling
    • All stars rendered regardless of visibility

7.2 Existing Optimizations

POSITIVE:
✓ Procedural generation for backgrounds (saves ~10 MB+ in textures)
✓ useGLTF.preload() for probe models
✓ useTexture hook caching
✓ Lazy loading for non-critical UI components
✓ Reused geometry for identical objects (stars use single SphereGeometry)
✓ Billboard optimization for labels (distance culling)
✓ Selective texture filtering (excludes atmosphere/night variants)

8. Performance Summary

Asset Totals:

  • Textures: 19 MB (backend) / 7.9 MB (dist)
  • Models: 24 MB (backend) / 12.8 MB (dist)
  • JavaScript: 1.2 MB
  • Total Transfer: ~32 MB initial + on-demand loading

Loading Pattern:

  • Initial Load: 1.2 MB (JS) + procedural background rendering
  • Per-Scene: ~100-500 KB (depending on visible bodies)
  • Per-Probe: 280 KB - 8.6 MB (first load)

Current Bottlenecks:

  1. Juno probe (8.6 MB) loading time
  2. Sequential texture API calls
  3. No partial/progressive loading
  4. Large JPEG files (Moon: 1 MB, Venus: 868 KB)

9. File Locations Summary

Source Code:

  • Main 3D Scene: /Users/jiliu/WorkSpace/cosmo/frontend/src/components/Scene.tsx
  • Texture Loading: /Users/jiliu/WorkSpace/cosmo/frontend/src/components/CelestialBody.tsx (Line 102-123)
  • Model Loading: /Users/jiliu/WorkSpace/cosmo/frontend/src/components/Probe.tsx (Line 261-295)
  • API Integration: /Users/jiliu/WorkSpace/cosmo/frontend/src/utils/api.ts
  • Build Config: /Users/jiliu/WorkSpace/cosmo/frontend/vite.config.ts

Asset Locations:

  • Texture Source: /Users/jiliu/WorkSpace/cosmo/backend/upload/texture/
  • Model Source: /Users/jiliu/WorkSpace/cosmo/backend/upload/model/
  • Texture Build Output: /Users/jiliu/WorkSpace/cosmo/frontend/dist/textures/
  • Model Build Output: /Users/jiliu/WorkSpace/cosmo/frontend/dist/models/
  • Documentation: /Users/jiliu/WorkSpace/cosmo/frontend/PERFORMANCE_OPTIMIZATION.md

10. Recommendations (Priority Order)

Quick Wins (1-2 hours):

  1. Implement image compression (JPEG quality: 80-85%)
  2. Add WebP format with JPEG fallback
  3. Set proper Cache-Control headers on backend
  4. Implement batch/parallel texture loading

Medium Term (4-8 hours):

  1. Add texture LOD (Load specific resolution by distance)
  2. Implement model decimation for Juno probe
  3. Add progressive texture loading (low-res → high-res)
  4. Implement frustum culling for star systems

Long Term (16+ hours):

  1. Implement texture atlas for small textures
  2. Add KTX2/Basis texture compression
  3. Implement virtual scrolling for star catalog
  4. Add service worker for persistent caching