140 lines
4.6 KiB
Rust
140 lines
4.6 KiB
Rust
use block_mesh::Voxel;
|
|
|
|
use crate::space::two_dimensional::depth_tiles::{DepthTile, Direction};
|
|
|
|
use super::{traits::VoxelContainer, vec3generic::Vec3Generic};
|
|
|
|
#[derive(Debug)]
|
|
struct VoxelCursor<TVoxel> {
|
|
position: Vec3Generic<i32>,
|
|
finished: bool,
|
|
found: Option<TVoxel>,
|
|
}
|
|
|
|
impl<T> VoxelCursor<T> {
|
|
pub fn new(position: Vec3Generic<i32>) -> VoxelCursor<T> {
|
|
VoxelCursor::<T> {
|
|
position,
|
|
finished: false,
|
|
found: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn create_tilemap<TContainer, TVoxel>(
|
|
container: &TContainer,
|
|
direction: Direction,
|
|
width: u32,
|
|
height: u32,
|
|
search_depth: u32,
|
|
) -> Vec<DepthTile<TVoxel>>
|
|
where
|
|
TContainer: VoxelContainer<TVoxel>,
|
|
TVoxel: Voxel + Copy + Default,
|
|
{
|
|
let step = match direction {
|
|
Direction::North => Vec3Generic::<i32> { x: 0, y: 0, z: 1 },
|
|
Direction::South => Vec3Generic::<i32> { x: 0, y: 0, z: -1 },
|
|
Direction::East => Vec3Generic::<i32> { x: 1, y: 0, z: 0 },
|
|
Direction::West => Vec3Generic::<i32> { x: -1, y: 0, z: 0 },
|
|
};
|
|
|
|
// create a bunch of cursors
|
|
let mut cursors: Vec<VoxelCursor<TVoxel>> = vec![];
|
|
for x in 0..width as i32 {
|
|
for y in 0..height as i32 {
|
|
cursors.push(match direction {
|
|
Direction::North => VoxelCursor::new(Vec3Generic::<i32> { x, y, z: 0 }),
|
|
Direction::South => VoxelCursor::new(Vec3Generic::<i32> {
|
|
x,
|
|
y,
|
|
z: search_depth as i32 - 1,
|
|
}),
|
|
Direction::East => VoxelCursor::new(Vec3Generic::<i32> { x: 0, y, z: x }),
|
|
Direction::West => VoxelCursor::new(Vec3Generic::<i32> {
|
|
x: search_depth as i32 - 1,
|
|
y,
|
|
z: x,
|
|
}),
|
|
});
|
|
}
|
|
}
|
|
|
|
// move them each until they bump into something.
|
|
// spec: https://www.youtube.com/watch?v=wwvLlEtxX3o
|
|
let mut num_finished_cursors = 0;
|
|
while num_finished_cursors < cursors.len() - 1 {
|
|
println!(
|
|
"num finished cursors: {}/{}",
|
|
num_finished_cursors,
|
|
cursors.len()
|
|
);
|
|
for cursor in &mut cursors {
|
|
if cursor.finished {
|
|
continue;
|
|
}
|
|
|
|
// is there a visible voxel at the current location? if so, we're done.
|
|
match container.get_voxel_at_pos(cursor.position) {
|
|
Some(v) => match v.get_visibility() {
|
|
block_mesh::VoxelVisibility::Opaque
|
|
| block_mesh::VoxelVisibility::Translucent => {
|
|
cursor.found = Some(v);
|
|
cursor.finished = true;
|
|
num_finished_cursors += 1;
|
|
continue;
|
|
}
|
|
block_mesh::VoxelVisibility::Empty => (),
|
|
},
|
|
None => (),
|
|
};
|
|
|
|
// step the cursor
|
|
cursor.position = cursor.position + step;
|
|
|
|
// test if the cursor is out of bounds (any dimension is outside of 0 <= n < search_depth)
|
|
for n in [&cursor.position.x, &cursor.position.y, &cursor.position.z] {
|
|
if *n < 0 || *n > search_depth as i32 {
|
|
cursor.finished = true;
|
|
num_finished_cursors += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
println!("all cursors finished.");
|
|
|
|
// todo: do we need to normalize the depth relative to camera? i.e. closest layer is depth 0
|
|
// even if it was on the backside
|
|
|
|
let mut tiles: Vec<DepthTile<TVoxel>> = vec![];
|
|
for cursor in cursors {
|
|
match cursor.found {
|
|
Some(v) => {
|
|
// determine the x, y, and depth based on the direction and the voxel's vector
|
|
let (x, y, depth) = match direction {
|
|
Direction::North => (cursor.position.x, cursor.position.y, cursor.position.z),
|
|
Direction::South => (
|
|
cursor.position.x,
|
|
cursor.position.y,
|
|
cursor.position.z,
|
|
), // flip x and z
|
|
Direction::East => (cursor.position.z, cursor.position.y, cursor.position.x),
|
|
Direction::West => (
|
|
cursor.position.z,
|
|
cursor.position.y,
|
|
cursor.position.x,
|
|
),
|
|
};
|
|
tiles.push(DepthTile::<TVoxel> {
|
|
x,
|
|
y,
|
|
depth,
|
|
data: v,
|
|
});
|
|
}
|
|
None => (),
|
|
}
|
|
}
|
|
tiles
|
|
}
|