Model Cache Integrity Fix
Overview
The model cache now correctly preserves the original index buffer type (Uint16Array vs Uint32Array) when caching and restoring GLB models. This fixes silent geometry corruption and RangeError crashes that occurred when cached models were restored.The Problem
Root Cause
When GLB models were cached, the index buffer type information was lost. On cache restore:- Original model loaded with Uint32Array indices (for meshes with >65535 vertices)
- Cache saved geometry data but not the index buffer type
- Cache restored with default Uint16Array indices
- Result: Silent geometry corruption or RangeError crashes
Symptoms
Silent Corruption:- Models render with incorrect triangles
- Geometry appears “broken” or “inside-out”
- No error messages in console
Affected Models
All GLB models loaded via ModelCache:- Resource models (trees, rocks, ores, herbs)
- NPC models (mobs, NPCs)
- Item models (equipment, weapons, tools)
- Building models (structures, props)
The Solution
Index Buffer Type Preservation
The model cache now stores and restores the index buffer type:Cache Version Bump
Cache version bumped from 3 to 4 to invalidate corrupt entries:Technical Details
Index Buffer Types
Uint16Array (2 bytes per index):- Maximum vertex count: 65,535
- Used for simple models (most resources, items)
- More memory efficient
- Maximum vertex count: 4,294,967,295
- Required for complex models (large buildings, detailed NPCs)
- Uses more memory but supports larger meshes
Detection Logic
Restoration Logic
Impact
Performance
No performance impact:- Index buffer type detection is O(1)
- Cache save/restore time unchanged
- Memory usage unchanged (type was always stored, just not preserved)
Compatibility
Breaking change for cache:- Cache version 3 entries are automatically invalidated
- Models are re-processed on first load after update
- Subsequent loads use correct cached data
- All existing code continues to work
- No API changes required
- Automatic fallback to individual models if instancing fails
Verification
How to Verify Fix
- Clear cache (optional, happens automatically with version bump):
- Load a complex model (>65535 vertices):
- Check index buffer type:
- Verify no RangeError:
- Load model multiple times (first load caches, second load restores)
- No RangeError should occur
- Geometry should render correctly
Test Coverage
The fix is covered by existing tests:ModelCache.test.ts- Verifies cache save/restoreGLBResourceInstancer.test.ts- Verifies instanced renderingResourceSystem.test.ts- Integration tests for resource loading
Related Issues
PR #949
Title: fix: preserve index buffer type in processed model cache Changes:- Added
indexTypefield to cached geometry data - Implemented type detection in cache save
- Implemented type restoration in cache load
- Bumped cache version to 4
afb5ba2de0d97f3ac3175a22bdef90922d79b7d9
Migration Notes
For Developers
No action required - the fix is automatic:- Cache version bump invalidates old entries
- Models are re-cached with correct index buffer types
- All subsequent loads use correct data
For Users
No action required - transparent fix:- First load after update may be slightly slower (re-caching)
- Subsequent loads are normal speed
- No visual changes or gameplay impact
Future Improvements
Potential Optimizations
-
Lazy index buffer allocation
- Only allocate Uint32Array when needed
- Convert Uint16Array to Uint32Array on demand
- Saves memory for simple models
-
Index buffer compression
- Use mesh optimizer for index buffer compression
- Reduce cache size by 50-70%
- Decompress on load
-
Shared index buffers
- Share index buffers between instances
- Further reduce memory usage
- Requires geometry instancing support
References
- Model Cache:
packages/shared/src/utils/rendering/ModelCache.ts - GLB Resource Instancer:
packages/shared/src/systems/shared/world/GLBResourceInstancer.ts - GLB Tree Instancer:
packages/shared/src/systems/shared/world/GLBTreeInstancer.ts - Three.js BufferGeometry: https://threejs.org/docs/#api/en/core/BufferGeometry