block_mesh/
lib.rs

1//! [![Crates.io](https://img.shields.io/crates/v/block-mesh.svg)](https://crates.io/crates/block-mesh)
2//! [![Docs.rs](https://docs.rs/block-mesh/badge.svg)](https://docs.rs/block-mesh)
3//!
4//! Fast algorithms for generating voxel block meshes.
5//!
6//! ![Mesh Examples](https://raw.githubusercontent.com/bonsairobo/block-mesh-rs/main/examples-crate/render/mesh_examples.png)
7//!
8//! Two algorithms are included:
9//! - [`visible_block_faces`](crate::visible_block_faces): very fast but suboptimal meshes
10//! - [`greedy_quads`](crate::greedy_quads): not quite as fast, but far fewer triangles are generated
11//!
12//! Benchmarks show that [`visible_block_faces`](crate::visible_block_faces) generates about 40 million quads per second on a
13//! single core of a 2.5 GHz Intel Core i7. Assuming spherical input data, [`greedy_quads`](crate::greedy_quads) can generate a
14//! more optimal version of the same mesh with 1/3 of the quads, but it takes about 3 times longer. To run the benchmarks
15//! yourself, `cd bench/ && cargo bench`.
16//!
17//! # Example Code
18//!
19//! ```
20//! use block_mesh::ndshape::{ConstShape, ConstShape3u32};
21//! use block_mesh::{greedy_quads, GreedyQuadsBuffer, MergeVoxel, Voxel, VoxelVisibility, RIGHT_HANDED_Y_UP_CONFIG};
22//!
23//! #[derive(Clone, Copy, Eq, PartialEq)]
24//! struct BoolVoxel(bool);
25//!
26//! const EMPTY: BoolVoxel = BoolVoxel(false);
27//! const FULL: BoolVoxel = BoolVoxel(true);
28//!
29//! impl Voxel for BoolVoxel {
30//!     fn get_visibility(&self) -> VoxelVisibility {
31//!         if *self == EMPTY {
32//!             VoxelVisibility::Empty
33//!         } else {
34//!             VoxelVisibility::Opaque
35//!         }
36//!     }
37//! }
38//!
39//! impl MergeVoxel for BoolVoxel {
40//!     type MergeValue = Self;
41//!
42//!     fn merge_value(&self) -> Self::MergeValue {
43//!         *self
44//!     }
45//! }
46//!
47//! // A 16^3 chunk with 1-voxel boundary padding.
48//! type ChunkShape = ConstShape3u32<18, 18, 18>;
49//!
50//! // This chunk will cover just a single octant of a sphere SDF (radius 15).
51//! let mut voxels = [EMPTY; ChunkShape::SIZE as usize];
52//! for i in 0..ChunkShape::SIZE {
53//!     let [x, y, z] = ChunkShape::delinearize(i);
54//!     voxels[i as usize] = if ((x * x + y * y + z * z) as f32).sqrt() < 15.0 {
55//!         FULL
56//!     } else {
57//!         EMPTY
58//!     };
59//! }
60//!
61//! let mut buffer = GreedyQuadsBuffer::new(voxels.len());
62//! greedy_quads(
63//!     &voxels,
64//!     &ChunkShape {},
65//!     [0; 3],
66//!     [17; 3],
67//!     &RIGHT_HANDED_Y_UP_CONFIG.faces,
68//!     &mut buffer
69//! );
70//!
71//! // Some quads were generated.
72//! assert!(buffer.quads.num_quads() > 0);
73//! ```
74
75mod bounds;
76mod buffer;
77pub mod geometry;
78mod greedy;
79mod simple;
80
81pub use buffer::*;
82#[doc(inline)]
83pub use geometry::*;
84pub use greedy::*;
85pub use simple::*;
86
87pub use ilattice;
88pub use ndshape;
89
90/// Describes how this voxel influences mesh generation.
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92pub enum VoxelVisibility {
93    /// This voxel should not produce any geometry.
94    Empty,
95    /// Should produce geometry, and also light can pass through.
96    Translucent,
97    /// Light cannot pass through this voxel.
98    Opaque,
99}
100
101/// Implement on your voxel types to inform the library
102/// how to generate geometry for this voxel.
103pub trait Voxel {
104    fn get_visibility(&self) -> VoxelVisibility;
105}
106
107/// Used as a dummy for functions that must wrap a voxel
108/// but don't want to change the original's properties.
109struct IdentityVoxel<'a, T: Voxel>(&'a T);
110
111impl<'a, T: Voxel> Voxel for IdentityVoxel<'a, T> {
112    #[inline]
113    fn get_visibility(&self) -> VoxelVisibility {
114        self.0.get_visibility()
115    }
116}
117
118impl<'a, T: Voxel> From<&'a T> for IdentityVoxel<'a, T> {
119    fn from(voxel: &'a T) -> Self {
120        Self(voxel)
121    }
122}