Problem
Chunk cells use Box<[Option<Color8>]> (src/grid.rs:29, Color8 = [u8; 4]).
[u8; 4] uses all 256 bit patterns per byte, so Option<[u8; 4]> has no niche — it needs a separate discriminant byte:
size_of::<Option<[u8; 4]>>() == 5
Storage is dense, not sparse: a chunk allocates the full CHUNK_VOL array on first write regardless of fill.
- 5 B × 32,768 (
CHUNK_VOL) = 160 KB / allocated chunk
- × 4,000 (
LARGE_SCENE_CHUNKS, src/grid.rs:15) = ~640 MB for cell arrays alone
This caps practical scene size well below an "open world" target.
Proposed fix (~4-5x cut)
Palette-indexed cells + separate occupancy bitset:
palette: Vec<Color8> (per-grid or global) + chunk stores Box<[u8; CHUNK_VOL]> palette indices
- occupancy
Box<[u64; CHUNK_VOL / 64]> bitset (512 B/chunk) replaces the Option tag
get: bitset bit -> palette index -> color
set: intern color, set bit + write index
Per chunk: 32,768 (u8 index) + 512 (bitset) = ~32.5 KB -> ~4.9x smaller. 640 MB -> ~130 MB.
Caveats / scope
- 256-color cap per palette with
u8 index. If scenes exceed 256 distinct colors, need u16 index (2x) or per-chunk palettes. Roxel is already palette-oriented (palettes.ron).
set's drop-on-empty, occupancy count, and seam-dirty logic all need rework (src/grid.rs:111-176).
- Touches mesher + picking read paths (they call
get).
- Prototype behind the existing
get/set API so callers don't change.
Priority
Flag, not emergency. No correctness bug today — purely a scaling ceiling.
Problem
Chunk cells use
Box<[Option<Color8>]>(src/grid.rs:29,Color8 = [u8; 4]).[u8; 4]uses all 256 bit patterns per byte, soOption<[u8; 4]>has no niche — it needs a separate discriminant byte:Storage is dense, not sparse: a chunk allocates the full
CHUNK_VOLarray on first write regardless of fill.CHUNK_VOL) = 160 KB / allocated chunkLARGE_SCENE_CHUNKS,src/grid.rs:15) = ~640 MB for cell arrays aloneThis caps practical scene size well below an "open world" target.
Proposed fix (~4-5x cut)
Palette-indexed cells + separate occupancy bitset:
palette: Vec<Color8>(per-grid or global) + chunk storesBox<[u8; CHUNK_VOL]>palette indicesBox<[u64; CHUNK_VOL / 64]>bitset (512 B/chunk) replaces theOptiontagget: bitset bit -> palette index -> colorset: intern color, set bit + write indexPer chunk: 32,768 (u8 index) + 512 (bitset) = ~32.5 KB -> ~4.9x smaller. 640 MB -> ~130 MB.
Caveats / scope
u8index. If scenes exceed 256 distinct colors, needu16index (2x) or per-chunk palettes. Roxel is already palette-oriented (palettes.ron).set's drop-on-empty, occupancycount, and seam-dirty logic all need rework (src/grid.rs:111-176).get).get/setAPI so callers don't change.Priority
Flag, not emergency. No correctness bug today — purely a scaling ceiling.