@holoscript/streaming
v1.0.0
Published
Asset and world streaming - progressive loading and LOD streaming for VR
Maintainers
Readme
@holoscript/streaming
Asset and world streaming for HoloScript VR/AR
Progressive loading, LOD streaming, and smart caching for large VR worlds.
Features
- 📦 Progressive Loading — Load assets in priority order
- 🎯 LOD Streaming — Stream level-of-detail based on camera distance
- 🗄️ Smart Caching — Memory + IndexedDB with automatic eviction
- 📊 Memory Budget — Stay within hardware limits
- 🔗 Bundle Support — Load asset bundles efficiently
Installation
npm install @holoscript/streamingQuick Start
import { AssetLoader, CacheManager } from '@holoscript/streaming';
// Create loader with caching
const cache = new CacheManager({
maxMemoryMB: 512,
indexedDBName: 'holoscript-assets',
});
const loader = new AssetLoader({ cache });
// Load an asset
const model = await loader.load({
id: 'character-model',
url: '/models/character.glb',
type: AssetType.Model,
priority: LoadPriority.High,
});Asset Loading
Basic Loading
import { AssetLoader, AssetType, LoadPriority } from '@holoscript/streaming';
const loader = new AssetLoader();
// Load with priority
const texture = await loader.load({
id: 'hero-texture',
url: '/textures/hero.png',
type: AssetType.Texture,
priority: LoadPriority.Immediate,
});
// Load in background
const ambientAudio = await loader.load({
id: 'ambient-sound',
url: '/audio/forest.mp3',
type: AssetType.Audio,
priority: LoadPriority.Background,
});Progress Tracking
const asset = await loader.load({
id: 'large-model',
url: '/models/world.glb',
type: AssetType.Model,
priority: LoadPriority.Normal,
onProgress: (progress) => {
console.log(`${progress.phase}: ${(progress.progress * 100).toFixed(1)}%`);
console.log(`ETA: ${progress.estimatedTimeRemaining}ms`);
},
});Queue Management
import { LoadQueue } from '@holoscript/streaming';
const queue = new LoadQueue({
maxConcurrentDownloads: 4,
maxConcurrentProcessing: 2,
timeout: 30000,
});
// Add multiple assets
queue.enqueue([
{ id: 'tex1', url: '/t1.png', type: AssetType.Texture, priority: LoadPriority.High },
{ id: 'tex2', url: '/t2.png', type: AssetType.Texture, priority: LoadPriority.Normal },
{ id: 'tex3', url: '/t3.png', type: AssetType.Texture, priority: LoadPriority.Low },
]);
// Higher priority assets load first
await queue.processAll();Progressive Loading
Load assets in stages for faster initial display:
import { ProgressiveLoader } from '@holoscript/streaming';
const progressive = new ProgressiveLoader();
// Load low-res first, then upgrade
const model = await progressive.loadProgressive({
id: 'terrain',
stages: [
{ url: '/terrain-low.glb', lodLevel: 2 },
{ url: '/terrain-med.glb', lodLevel: 1 },
{ url: '/terrain-high.glb', lodLevel: 0 },
],
onStageComplete: (stage, data) => {
scene.updateTerrain(data); // Show each stage as it loads
},
});Bundle Loading
Load related assets together:
import { BundleLoader } from '@holoscript/streaming';
const bundleLoader = new BundleLoader();
// Load a complete character bundle
const characterBundle = await bundleLoader.loadBundle({
id: 'player-character',
url: '/bundles/player.bundle',
manifest: {
model: 'character.glb',
textures: ['diffuse.png', 'normal.png'],
animations: ['idle.anim', 'walk.anim', 'run.anim'],
},
});
// Access individual assets
const model = characterBundle.get('model');
const walkAnim = characterBundle.get('animations/walk.anim');Caching
Memory Cache
Fast in-memory cache:
import { MemoryCache } from '@holoscript/streaming';
const memCache = new MemoryCache({
maxSizeMB: 256,
evictionPolicy: 'lru', // Least recently used
});
memCache.set('texture-1', textureData);
const cached = memCache.get('texture-1');IndexedDB Cache
Persistent browser storage:
import { IndexedDBCache } from '@holoscript/streaming';
const dbCache = new IndexedDBCache({
dbName: 'holoscript-cache',
maxSizeMB: 1024,
});
await dbCache.set('model-1', modelData);
const cached = await dbCache.get('model-1');Cache Manager
Unified cache with automatic tiering:
import { CacheManager } from '@holoscript/streaming';
const cache = new CacheManager({
maxMemoryMB: 512,
maxDiskMB: 2048,
indexedDBName: 'my-game-cache',
});
// Automatically uses memory first, falls back to disk
const asset = await cache.get('large-asset');
// Clear old entries
await cache.evict({ olderThan: Date.now() - 86400000 }); // 24 hoursMemory Budget
Stay within hardware limits:
import { MemoryBudgetMonitor } from '@holoscript/streaming';
const monitor = new MemoryBudgetMonitor({
budgetMB: 512,
warningThreshold: 0.8, // 80%
criticalThreshold: 0.95, // 95%
});
monitor.onWarning(() => {
console.log('Memory usage high, reducing quality');
loader.setMaxLOD(1); // Limit to medium quality
});
monitor.onCritical(() => {
console.log('Memory critical, unloading distant assets');
loader.unloadDistant(playerPosition, 100); // Unload assets > 100m away
});
// Check current usage
console.log(`Memory: ${monitor.usedMB}MB / ${monitor.budgetMB}MB`);Asset Types
| Type | Description | Extensions |
|------|-------------|------------|
| Mesh | 3D geometry | .obj, .fbx |
| Model | Complete 3D model | .glb, .gltf |
| Texture | 2D images | .png, .jpg, .webp |
| Material | Material definitions | .mat |
| Audio | Sound files | .mp3, .ogg, .wav |
| Animation | Animation clips | .anim |
| Script | HoloScript files | .hs, .hsplus, .holo |
| Scene | Complete scenes | .scene |
| Prefab | Reusable objects | .prefab |
| Shader | Custom shaders | .glsl, .wgsl |
Load Priorities
| Priority | Value | Use Case |
|----------|-------|----------|
| Background | 0 | Prefetching, non-visible |
| Low | 1 | Distant objects |
| Normal | 2 | Default priority |
| High | 3 | Player-facing content |
| Immediate | 4 | Blocking, must-have |
Integration with HoloScript
Use with streaming traits in .hsplus files:
composition "Large World" {
assets {
bundle "environment" {
progressive: true
lod_levels: 3
preload_distance: 100
}
}
spatial_group "Zone_A" @streaming {
load_distance: 200
unload_distance: 300
lod_bias: 1
}
}Types
import type {
AssetType,
AssetState,
AssetInfo,
LoadedAsset,
LoadPriority,
LoadRequest,
LoadProgress,
} from '@holoscript/streaming';License
MIT © Brian Joseph
