Model Cache Fixes (February 2026)
Commit: c98f1cce4240b5d4d7a459f60f47a927fe606d2bPR: #935
Author: tcm390
Summary
Fixed two critical bugs in the IndexedDB processed model cache that caused missing objects (altars, trees) and lost textures (white/wrong colors) after browser restart.Bug 1: Missing Objects
Symptoms
- Objects disappear after browser restart
- Common missing objects: altars, trees, rocks
- Models with duplicate mesh names affected most
Root Cause
serializeNode() used findIndex-by-name to map hierarchy nodes to mesh data:
Three.js add() auto-removes from previous parent, so only the last reference survived.
Fix
UseMap<Object3D, number> identity map built during traversal:
Bug 2: Lost Textures
Symptoms
- Textures appear white or wrong color after browser restart
- Affects all textured models
- Cache appears to load but materials are broken
Root Cause
Textures were serialized as ephemeralblob: URLs but never reloaded during deserialization:
Fix
Extract raw RGBA pixels via canvasgetImageData() (synchronous) and restore as THREE.DataTexture:
Additional Fix: Grey Tree Materials
Symptom
Trees appear grey instead of green after cache load.Root Cause
createDissolveMaterial() used instanceof MeshStandardMaterial which fails for MeshStandardNodeMaterial in the WebGPU build:
Fix
Replace with duck-type property check:Cache Version Bump
BumpedPROCESSED_CACHE_VERSION from 2 to 3 to invalidate broken cache entries:
Debugging Tools
Disable Cache
Clear Cache
Inspect Cache
Error Logging
Cache errors are now logged to console:Performance Impact
Cache Hit (After Fix)
- Load Time: ~50ms (IndexedDB read + deserialization)
- Texture Restoration: Synchronous (no async loading)
- Memory: Same as uncached (DataTexture uses same memory as Image)
Cache Miss
- Load Time: ~500-2000ms (GLTF parse + processing)
- Texture Loading: Async (may cause flicker)
- Memory: Same (textures loaded either way)
Migration Guide
For Users
No action needed - cache version bump triggers automatic rebuild. If you see missing objects or white textures:- Clear cache:
indexedDB.deleteDatabase('hyperscape-processed-models') - Reload page
- Cache will rebuild with fixed serialization
For Developers
Testing cache serialization:Related Issues
Duplicate Mesh Names
Common Patterns:- Blender exports: "", “Cube”, “Cube.001”, “Cube.002”
- GLTF defaults: “Mesh_0”, “Mesh_1”, “Mesh_1” (duplicate)
- Empty names: "", "", ""
Blob URL Lifecycle
Why blob: URLs fail:- Created via
URL.createObjectURL(blob) - Valid only for current page session
- Revoked on page unload or manual
URL.revokeObjectURL() - Invalid after browser restart
Testing
Test Cases
packages/shared/src/utils/rendering/tests/ModelCache.test.ts:References
- ModelCache.ts - Implementation
- Three.js DataTexture - Texture API
- IndexedDB API - Browser storage