Expand description
block-mesh-compatible binary greedy meshing.
binary_greedy_quads mirrors the call shape of
block_mesh::greedy_quads, but it reaches the same kind of QuadBuffer
through a different internal pipeline:
- Validate the padded query extent and precompute a few indexing facts.
- Build packed occupancy columns, one
u64per orthogonal column. - Turn those columns into visible-face rows with cheap bitwise tests.
- Merge each face slice into quads, either as unit quads or with a carry-based greedy row merger.
The implementation is split into the same stages in source:
context: query validation and precomputed layout factsprep: occupancy columns and visible-face rowsmerge: unit emission and carry-based greedy mergingao: AO-safe alternate merge policy built on binary occupancy masksface: face-orientation helpers shared by the other stages
The crate exposes two public entry points:
binary_greedy_quads: the current maximum-merge implementation with no extra policy checksbinary_greedy_quads_ao_safe: the same visibility pipeline, but with AO-safe merge restrictions for opaque faces
§AO-safe mode
AO-safe mode keeps the same prep pipeline as vanilla meshing. The difference is only in how face rows are merged:
- vanilla merging only checks
MergeVoxel::merge_value() - AO-safe merging also looks at opaque occupancy in the plane just outside the visible face
- from that exterior plane it derives whole-row binary masks that prove which cells must stay unit, which may only merge in one direction, and which are still free to use the normal carry merge
That keeps the AO rule in terms of the same binary data the mesher already uses elsewhere, instead of carrying per-cell lighting data through the hot merge loop.
§Terminology
The source uses three axis names repeatedly:
n_axis: the face normal axisouter_axis: the axis that advances from one row to the next within a face slicebit_axis: the axis packed into the row’su64bitset
Every meshed query is also split into two nested boxes:
- the query extent
[min, max], which includes one voxel of padding on every side - the interior extent
[min + 1, max - 1], whose faces may actually produce quads
The padding is never emitted. It only exists so the mesher can decide whether an interior face is visible.
§Why the 62-voxel limit exists
Each axis of the padded query is packed into one u64. That leaves room for
at most 62 interior voxels plus the two required padding voxels.
§Example
use block_mesh::ndshape::{ConstShape, ConstShape3u32};
use block_mesh::{
MergeVoxel, Voxel, VoxelVisibility, RIGHT_HANDED_Y_UP_CONFIG,
};
use block_mesh_bgm::{binary_greedy_quads, BinaryGreedyQuadsBuffer};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct BoolVoxel(bool);
const EMPTY: BoolVoxel = BoolVoxel(false);
const FULL: BoolVoxel = BoolVoxel(true);
impl Voxel for BoolVoxel {
fn get_visibility(&self) -> VoxelVisibility {
if *self == EMPTY {
VoxelVisibility::Empty
} else {
VoxelVisibility::Opaque
}
}
}
impl MergeVoxel for BoolVoxel {
type MergeValue = Self;
fn merge_value(&self) -> Self::MergeValue {
*self
}
}
type ChunkShape = ConstShape3u32<18, 18, 18>;
let mut voxels = [EMPTY; ChunkShape::SIZE as usize];
for i in 0..ChunkShape::SIZE {
let [x, y, z] = ChunkShape::delinearize(i);
voxels[i as usize] = if ((x * x + y * y + z * z) as f32).sqrt() < 15.0 {
FULL
} else {
EMPTY
};
}
let mut buffer = BinaryGreedyQuadsBuffer::new();
binary_greedy_quads(
&voxels,
&ChunkShape {},
[0; 3],
[17; 3],
&RIGHT_HANDED_Y_UP_CONFIG.faces,
&mut buffer,
);
assert!(buffer.quads.num_quads() > 0);The AO-safe entry point uses the same buffer type:
let mut buffer = BinaryGreedyQuadsBuffer::new();
binary_greedy_quads_ao_safe(
&voxels,
&ChunkShape {},
[0; 3],
[3; 3],
&RIGHT_HANDED_Y_UP_CONFIG.faces,
&mut buffer,
);Structs§
- Binary
Greedy Quads Buffer - Reusable output and scratch storage for
binary_greedy_quadsandbinary_greedy_quads_ao_safe.
Functions§
- binary_
greedy_ quads - Generates greedy quads using a binary-mask-backed implementation.
- binary_
greedy_ quads_ ao_ safe - Generates greedy quads with AO-safe merge restrictions for opaque faces.