Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change texture index to generic type #39

Merged
merged 8 commits into from
Nov 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Rename Index -> MaterialIndex
  • Loading branch information
splashdust committed Nov 17, 2024
commit 4690a491be1cf634e1c4ebd2c8ffbedc0a03f37a
6 changes: 3 additions & 3 deletions examples/bombs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use std::time::Duration;
struct MainWorld;

impl VoxelWorldConfig for MainWorld {
type Index = u8;
type MaterialIndex = u8;
fn spawning_distance(&self) -> u32 {
15
}

fn voxel_lookup_delegate(&self) -> VoxelLookupDelegate<Self::Index> {
fn voxel_lookup_delegate(&self) -> VoxelLookupDelegate<Self::MaterialIndex> {
Box::new(move |_chunk_pos| get_voxel_fn())
}
}
Expand Down Expand Up @@ -69,7 +69,7 @@ fn setup(mut commands: Commands) {
});
}

fn get_voxel_fn() -> Box<dyn FnMut(IVec3) -> WorldVoxel<u8> + Send + Sync> {
fn get_voxel_fn() -> Box<dyn FnMut(IVec3) -> WorldVoxel + Send + Sync> {
// Set up some noise to use as the terrain height map
let mut noise = HybridMulti::<Perlin>::new(1234);
noise.octaves = 4;
Expand Down
4 changes: 2 additions & 2 deletions examples/custom_material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ const BLUE: u8 = 2;
struct MyMainWorld;

impl VoxelWorldConfig for MyMainWorld {
type Index = u8;
fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::Index) -> [u32; 3] + Send + Sync> {
type MaterialIndex = u8;
fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::MaterialIndex) -> [u32; 3] + Send + Sync> {
Arc::new(|vox_mat: u8| match vox_mat {
RED => [1, 1, 1],
GREEN => [2, 2, 2],
Expand Down
2 changes: 1 addition & 1 deletion examples/fast_traversal_ray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct VoxelTrace {
}

impl VoxelWorldConfig for MyMainWorld {
type Index = u8;
type MaterialIndex = u8;

fn texture_index_mapper(&self) -> Arc<dyn Fn(u8) -> [u32; 3] + Send + Sync> {
Arc::new(|vox_mat: u8| match vox_mat {
Expand Down
6 changes: 3 additions & 3 deletions examples/multiple_worlds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ const BLUE: u8 = 2;
struct MainWorld;

impl VoxelWorldConfig for MainWorld {
type Index = u8;
type MaterialIndex = u8;

fn spawning_distance(&self) -> u32 {
10
}

fn voxel_lookup_delegate(&self) -> VoxelLookupDelegate<Self::Index> {
fn voxel_lookup_delegate(&self) -> VoxelLookupDelegate<Self::MaterialIndex> {
Box::new(move |_chunk_pos| get_voxel_fn())
}
}
Expand All @@ -42,7 +42,7 @@ impl VoxelWorldConfig for MainWorld {
struct SecondWorld;

impl VoxelWorldConfig for SecondWorld {
type Index = u8;
type MaterialIndex = u8;

fn texture_index_mapper(&self) -> Arc<dyn Fn(u8) -> [u32; 3] + Send + Sync> {
Arc::new(|vox_mat: u8| match vox_mat {
Expand Down
4 changes: 2 additions & 2 deletions examples/noise_terrain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ use noise::{HybridMulti, NoiseFn, Perlin};
struct MainWorld;

impl VoxelWorldConfig for MainWorld {
type Index = u8;
type MaterialIndex = u8;

fn spawning_distance(&self) -> u32 {
25
}

fn voxel_lookup_delegate(&self) -> VoxelLookupDelegate<Self::Index> {
fn voxel_lookup_delegate(&self) -> VoxelLookupDelegate<Self::MaterialIndex> {
Box::new(move |_chunk_pos| get_voxel_fn())
}
}
Expand Down
4 changes: 2 additions & 2 deletions examples/ray_cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ const GRASS: u8 = 2;
struct MyMainWorld;

impl VoxelWorldConfig for MyMainWorld {
type Index = u8;
type MaterialIndex = u8;

fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::Index) -> [u32; 3] + Send + Sync> {
fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::MaterialIndex) -> [u32; 3] + Send + Sync> {
Arc::new(|vox_mat: u8| match vox_mat {
SNOWY_BRICK => [0, 1, 2],
FULL_BRICK => [2, 2, 2],
Expand Down
4 changes: 2 additions & 2 deletions examples/textures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ const GRASS: u8 = 2;
struct MyMainWorld;

impl VoxelWorldConfig for MyMainWorld {
type Index = u8;
type MaterialIndex = u8;

fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::Index) -> [u32; 3] + Send + Sync> {
fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::MaterialIndex) -> [u32; 3] + Send + Sync> {
Arc::new(|vox_mat| match vox_mat {
SNOWY_BRICK => [0, 1, 2],
FULL_BRICK => [2, 2, 2],
Expand Down
4 changes: 2 additions & 2 deletions examples/textures_custom_idx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ enum BlockTexture {
struct MyMainWorld;

impl VoxelWorldConfig for MyMainWorld {
type Index = BlockTexture;
type MaterialIndex = BlockTexture;

fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::Index) -> [u32; 3] + Send + Sync> {
fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::MaterialIndex) -> [u32; 3] + Send + Sync> {
Arc::new(|vox_mat| match vox_mat {
BlockTexture::SnowyBrick => [0, 1, 2],
BlockTexture::FullBrick => [2, 2, 2],
Expand Down
10 changes: 5 additions & 5 deletions src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub enum ChunkSpawnStrategy {

/// `bevy_voxel_world` configuation structs need to implement this trait
pub trait VoxelWorldConfig: Resource + Default + Clone {
type Index: Copy + Hash + PartialEq + Eq + Default + Send + Sync;
type MaterialIndex: Copy + Hash + PartialEq + Eq + Default + Send + Sync;

/// Distance in chunks to spawn chunks around the camera
fn spawning_distance(&self) -> u32 {
Expand Down Expand Up @@ -82,7 +82,7 @@ pub trait VoxelWorldConfig: Resource + Default + Clone {
/// The three values correspond to the top, sides and bottom of the voxel. For example,
/// if the slice is `[1,2,2]`, the top will use texture index 1 and the sides and bottom will use texture
/// index 2.
fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::Index) -> [u32; 3] + Send + Sync> {
fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::MaterialIndex) -> [u32; 3] + Send + Sync> {
Arc::new(|mat| match mat {
_ => [0, 0, 0],
})
Expand All @@ -92,7 +92,7 @@ pub trait VoxelWorldConfig: Resource + Default + Clone {
/// The delegate will be called every time a new chunk needs to be computed. The delegate should
/// return a function that can be called to check if a voxel exists at a given position. This function
/// needs to be thread-safe, since chunk computation happens on a separate thread.
fn voxel_lookup_delegate(&self) -> VoxelLookupDelegate<Self::Index> {
fn voxel_lookup_delegate(&self) -> VoxelLookupDelegate<Self::MaterialIndex> {
Box::new(|_| Box::new(|_| WorldVoxel::Unset))
}

Expand All @@ -119,9 +119,9 @@ pub struct DefaultWorld;
impl DefaultWorld {}

impl VoxelWorldConfig for DefaultWorld {
type Index = u8;
type MaterialIndex = u8;

fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::Index) -> [u32; 3] + Send + Sync> {
fn texture_index_mapper(&self) -> Arc<dyn Fn(Self::MaterialIndex) -> [u32; 3] + Send + Sync> {
Arc::new(|mat| match mat {
0 => [0, 0, 0],
1 => [1, 1, 1],
Expand Down
7 changes: 6 additions & 1 deletion src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,12 @@ fn raycast_finds_voxel() {
Startup,
move |mut voxel_world: VoxelWorld<DefaultWorld>,
buffers: (
ResMut<ChunkMapUpdateBuffer<DefaultWorld, <DefaultWorld as VoxelWorldConfig>::Index>>,
ResMut<
ChunkMapUpdateBuffer<
DefaultWorld,
<DefaultWorld as VoxelWorldConfig>::MaterialIndex,
>,
>,
ResMut<MeshCacheInsertBuffer<DefaultWorld>>,
)| {
let test_voxel = crate::voxel::WorldVoxel::Solid(1);
Expand Down
27 changes: 14 additions & 13 deletions src/voxel_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,28 +99,28 @@ impl<I> VoxelRaycastResult<I> {
/// Grants access to the VoxelWorld in systems
#[derive(SystemParam)]
pub struct VoxelWorld<'w, C: VoxelWorldConfig> {
chunk_map: Res<'w, ChunkMap<C, <C as VoxelWorldConfig>::Index>>,
modified_voxels: Res<'w, ModifiedVoxels<C, <C as VoxelWorldConfig>::Index>>,
voxel_write_buffer: ResMut<'w, VoxelWriteBuffer<C, <C as VoxelWorldConfig>::Index>>,
chunk_map: Res<'w, ChunkMap<C, <C as VoxelWorldConfig>::MaterialIndex>>,
modified_voxels: Res<'w, ModifiedVoxels<C, <C as VoxelWorldConfig>::MaterialIndex>>,
voxel_write_buffer: ResMut<'w, VoxelWriteBuffer<C, <C as VoxelWorldConfig>::MaterialIndex>>,
#[allow(unused)]
configuration: Res<'w, C>,
}

impl<'w, C: VoxelWorldConfig> VoxelWorld<'w, C> {
/// Get the voxel at the given position. The voxel will be WorldVoxel::Unset if there is no voxel at that position
pub fn get_voxel(&self, position: IVec3) -> WorldVoxel<C::Index> {
pub fn get_voxel(&self, position: IVec3) -> WorldVoxel<C::MaterialIndex> {
self.get_voxel_fn()(position)
}

/// Set the voxel at the given position. This will create a new chunk if one does not exist at
/// the given position.
pub fn set_voxel(&mut self, position: IVec3, voxel: WorldVoxel<C::Index>) {
pub fn set_voxel(&mut self, position: IVec3, voxel: WorldVoxel<C::MaterialIndex>) {
self.voxel_write_buffer.push((position, voxel));
}

/// Get a sendable closure that can be used to get the voxel at the given position
/// This is useful for spawning tasks that need to access the voxel world
pub fn get_voxel_fn(&self) -> Arc<dyn Fn(IVec3) -> WorldVoxel<C::Index> + Send + Sync> {
pub fn get_voxel_fn(&self) -> Arc<dyn Fn(IVec3) -> WorldVoxel<C::MaterialIndex> + Send + Sync> {
let chunk_map = self.chunk_map.get_map();
let write_buffer = self.voxel_write_buffer.clone();
let modified_voxels = self.modified_voxels.clone();
Expand Down Expand Up @@ -160,7 +160,7 @@ impl<'w, C: VoxelWorldConfig> VoxelWorld<'w, C> {
pub fn get_closest_surface_voxel(
&self,
position: IVec3,
) -> Option<(IVec3, WorldVoxel<C::Index>)> {
) -> Option<(IVec3, WorldVoxel<C::MaterialIndex>)> {
let get_voxel = self.get_voxel_fn();
let mut current_pos = position;
let current_voxel = get_voxel(current_pos);
Expand Down Expand Up @@ -191,7 +191,7 @@ impl<'w, C: VoxelWorldConfig> VoxelWorld<'w, C> {
&self,
position: IVec3,
radius: u32,
) -> Option<(IVec3, WorldVoxel<C::Index>)> {
) -> Option<(IVec3, WorldVoxel<C::MaterialIndex>)> {
let mut tries = 0;

while tries < 100 {
Expand Down Expand Up @@ -224,7 +224,7 @@ impl<'w, C: VoxelWorldConfig> VoxelWorld<'w, C> {
pub fn get_surface_voxel_at_2d_pos(
&self,
pos_2d: Vec2,
) -> Option<(IVec3, WorldVoxel<C::Index>)> {
) -> Option<(IVec3, WorldVoxel<C::MaterialIndex>)> {
self.get_closest_surface_voxel(IVec3 {
x: pos_2d.x.floor() as i32,
y: 256,
Expand Down Expand Up @@ -264,22 +264,23 @@ impl<'w, C: VoxelWorldConfig> VoxelWorld<'w, C> {
pub fn raycast(
&self,
ray: Ray3d,
filter: &impl Fn((Vec3, WorldVoxel<C::Index>)) -> bool,
) -> Option<VoxelRaycastResult<C::Index>> {
filter: &impl Fn((Vec3, WorldVoxel<C::MaterialIndex>)) -> bool,
) -> Option<VoxelRaycastResult<C::MaterialIndex>> {
let raycast_fn = self.raycast_fn();
raycast_fn(ray, filter)
}

/// Get a sendable closure that can be used to raycast into the voxel world
pub fn raycast_fn(&self) -> Arc<RaycastFn<C::Index>> {
pub fn raycast_fn(&self) -> Arc<RaycastFn<C::MaterialIndex>> {
let chunk_map = self.chunk_map.get_map();
let get_voxel = self.get_voxel_fn();

Arc::new(move |ray, filter| {
let p = ray.origin;
let d = *ray.direction;

let loaded_aabb = ChunkMap::<C, C::Index>::get_world_bounds(&chunk_map.read().unwrap());
let loaded_aabb =
ChunkMap::<C, C::MaterialIndex>::get_world_bounds(&chunk_map.read().unwrap());
let trace_start =
if p.cmplt(loaded_aabb.min.into()).any() || p.cmpgt(loaded_aabb.max.into()).any() {
if let Some(trace_start_t) =
Expand Down
Loading