pub struct Grid {
pub transform: GridTransform,
pub chunks: HashMap<IVec3, Vxl>,
pub render_sky: bool,
pub mip_levels_override: Option<u32>,
}Expand description
One independent voxel grid in a scene. Holds its world placement and a sparse map of populated chunks. Empty chunk slots are implicit air and skipped during rendering / raycasts.
Each chunk is internally a Vxl with vsid = CHUNK_SIZE_XY
— the existing per-chunk renderer (opticast + grouscan +
sprites + lighting in roxlap-core) runs on each chunk
unchanged. Vertical worlds are built by stacking chunks along
grid-local +z.
Fields§
§transform: GridTransformWorld placement (origin + rotation).
chunks: HashMap<IVec3, Vxl>Sparse chunk storage keyed by (chx, chy, chz) chunk
coordinates. A missing entry means the chunk is fully air.
render_sky: boolWhether sky pixels rendered for this grid should be
composited into the final framebuffer. true is the
historical “grid owns its own sky” behaviour: ray misses
inside this grid’s frustum paint sky_color into the temp
buffer. Set false for grids that are a foreground object
(e.g. a ship) — the sky is owned by a single “world” grid
(the ground) and other grids should not contribute sky
pixels, otherwise their grid-local-frame sky lookup
rotates with the grid and visibly fights the world’s sky
during compose. See crate::render::render_scene_composed
for the masking implementation.
mip_levels_override: Option<u32>Override roxlap_core::opticast::OpticastSettings::mip_levels
for this grid. None ⇒ use the caller’s value. Some(n)
⇒ cap at n (clamped to [1, settings.mip_levels]). Use
to disable multi-mip on a per-grid basis — small grids
(rotating ships, billboards) don’t benefit from deep mips
and CAN trigger the
[[project_axis_aligned_mip_beams]]-style cf-cancellation
artifact when near-axis-aligned rays hit the rotated grid.
Some(1) = mip-0 only, byte-stable to single-mip.
Implementations§
Source§impl Grid
impl Grid
Sourcepub fn chunk(&self, chunk_idx: IVec3) -> Option<&Vxl>
pub fn chunk(&self, chunk_idx: IVec3) -> Option<&Vxl>
Borrow the chunk at chunk_idx if it has been materialised.
None means the chunk is implicitly all-air.
Sourcepub fn chunk_mut(&mut self, chunk_idx: IVec3) -> Option<&mut Vxl>
pub fn chunk_mut(&mut self, chunk_idx: IVec3) -> Option<&mut Vxl>
Mutably borrow a materialised chunk. Returns None for
implicit-air chunks; use Grid::ensure_chunk when you
need a &mut Vxl for an edit that may write voxels.
Sourcepub fn ensure_chunk(&mut self, chunk_idx: IVec3) -> &mut Vxl
pub fn ensure_chunk(&mut self, chunk_idx: IVec3) -> &mut Vxl
Borrow chunk_idx’s Vxl, creating an empty all-air
chunk first if it doesn’t exist yet. The returned &mut
is valid for editing via roxlap_formats::edit — the new
chunk has Vxl::reserve_edit_capacity already applied.
Sourcepub fn chunk_count(&self) -> usize
pub fn chunk_count(&self) -> usize
Number of materialised chunks. Implicit-air chunks don’t count.
Sourcepub fn chunk_xy_backing(&self) -> Option<ChunkXyBacking<'_>>
pub fn chunk_xy_backing(&self) -> Option<ChunkXyBacking<'_>>
S4B.2.c.3: build a per-chunk roxlap_core::GridView table
over this grid’s XY chunk footprint at chz = 0.
Returns None if no chz=0 chunk is populated (the entire
grid would render as implicit air anyway).
Iterates chunks once to find the chx/chy bounding box,
then a second time to fill the row-major
Vec<Option<GridView<'_>>>. Empty XY slots (implicit-air
chunks inside the box) get None.
Pair with roxlap_core::ChunkGrid + [roxlap_core:: GridView::from_chunk_grid] to drive the Approach B render
path:
let backing = grid.chunk_xy_backing().unwrap();
let cg = roxlap_core::ChunkGrid {
chunks: &backing.chunks,
origin_chunk_xy: backing.origin_chunk_xy,
chunks_x: backing.chunks_x,
chunks_y: backing.chunks_y,
};
let view = roxlap_core::GridView::from_chunk_grid(
&cg, crate::CHUNK_SIZE_XY,
);Only chz=0 chunks contribute (multi-z handoff lands in
S4B.3); higher-chz chunks in Self::chunks are ignored
here.
Sourcepub fn chunk_xyz_backing(&self) -> Option<ChunkXyBacking<'_>>
pub fn chunk_xyz_backing(&self) -> Option<ChunkXyBacking<'_>>
S4B.6.a: 3D-aware version of Self::chunk_xy_backing.
Enumerates ALL chunks across the chx/chy/chz bounding box
(not just chz=0) so a stacked grid can be rendered once
S4B.6.c switches the rasterizer to a chunk-z-aware column
walker.
Iterates chunks once for the XYZ bbox, then a second time
to fill the row-major-per-z Vec<Option<GridView<'_>>>.
Index layout: [(dz * chunks_y + dy) * chunks_x + dx] —
matches roxlap_core::ChunkGrid’s indexing exactly.
Returns None for empty grids.
Source§impl Grid
impl Grid
Sourcepub fn set_voxel(&mut self, voxel: IVec3, color: Option<u32>)
pub fn set_voxel(&mut self, voxel: IVec3, color: Option<u32>)
Set or carve a single voxel at grid-local coordinate
voxel. color = Some(c) inserts a solid voxel of colour
c; color = None carves to air.
Inserting in an implicit-air chunk materialises that chunk
(allocates a fresh Vxl); carving from a missing chunk
is a no-op.
Sourcepub fn set_rect(&mut self, lo: IVec3, hi: IVec3, color: Option<u32>)
pub fn set_rect(&mut self, lo: IVec3, hi: IVec3, color: Option<u32>)
Set or carve an axis-aligned box [lo, hi] in grid-local
voxel coordinates. Inclusive on both ends, like
roxlap_formats::edit::set_rect.
The box is decomposed per chunk: each touched chunk receives
a set_rect call with the box clipped to its footprint and
translated to chunk-local. Inserts materialise missing
chunks; carves skip them.
lo and hi may be in any order on each axis — the
decomposition normalises them.
Sourcepub fn set_sphere(&mut self, centre: IVec3, radius: u32, color: Option<u32>)
pub fn set_sphere(&mut self, centre: IVec3, radius: u32, color: Option<u32>)
Set or carve a sphere of voxels at grid-local centre
centre with the given radius. Euclidean distance, like
roxlap_formats::edit::set_sphere.
The bounding box of the sphere is enumerated chunk by chunk;
each touched chunk receives a set_sphere call with the
centre re-expressed in chunk-local coords (the per-chunk
call clips the sphere to the chunk’s footprint internally).
Chunks the sphere doesn’t actually reach get materialised
only if color.is_some() and they fall within the AABB —
the per-chunk set_sphere is a no-op for non-overlapping
chunks but the materialisation cost remains. A subsequent
pre-pass that filters chunks against radius² could avoid
this; out of scope for v1.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Grid
impl RefUnwindSafe for Grid
impl Send for Grid
impl Sync for Grid
impl Unpin for Grid
impl UnsafeUnpin for Grid
impl UnwindSafe for Grid
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more