2019-01-02 19:22:01 +00:00
|
|
|
use vek::*;
|
2019-04-23 22:48:31 +00:00
|
|
|
use crate::ray::{Ray, RayUntil};
|
2019-01-02 19:22:01 +00:00
|
|
|
|
2019-01-14 18:49:53 +00:00
|
|
|
/// A voxel
|
|
|
|
pub trait Vox {
|
|
|
|
fn empty() -> Self;
|
|
|
|
fn is_empty(&self) -> bool;
|
|
|
|
}
|
|
|
|
|
2019-01-13 20:53:55 +00:00
|
|
|
/// A volume that contains voxel data.
|
2019-01-02 19:22:01 +00:00
|
|
|
pub trait BaseVol {
|
2019-01-14 18:49:53 +00:00
|
|
|
type Vox: Vox;
|
2019-01-02 19:22:01 +00:00
|
|
|
type Err;
|
|
|
|
}
|
|
|
|
|
2019-01-13 20:53:55 +00:00
|
|
|
// Utility types
|
|
|
|
|
|
|
|
pub struct VoxPosIter {
|
|
|
|
pos: Vec3<u32>,
|
|
|
|
sz: Vec3<u32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for VoxPosIter {
|
|
|
|
type Item = Vec3<i32>;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
let mut old_pos = self.pos;
|
|
|
|
|
|
|
|
if old_pos.z == self.sz.z {
|
|
|
|
old_pos.z = 0;
|
|
|
|
old_pos.y += 1;
|
|
|
|
if old_pos.y == self.sz.y {
|
|
|
|
old_pos.y = 0;
|
|
|
|
old_pos.x += 1;
|
|
|
|
if old_pos.x == self.sz.x {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.pos = old_pos + Vec3::unit_z();
|
|
|
|
|
|
|
|
Some(old_pos.map(|e| e as i32))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A volume that has a finite size.
|
2019-01-02 19:22:01 +00:00
|
|
|
pub trait SizedVol: BaseVol {
|
2019-01-13 20:53:55 +00:00
|
|
|
/// Get the size of the volume.
|
|
|
|
#[inline(always)]
|
|
|
|
fn get_size(&self) -> Vec3<u32>;
|
|
|
|
|
|
|
|
/// Iterate through all potential voxel positions in this volume
|
|
|
|
fn iter_positions(&self) -> VoxPosIter {
|
|
|
|
VoxPosIter {
|
|
|
|
pos: Vec3::zero(),
|
|
|
|
sz: self.get_size(),
|
|
|
|
}
|
|
|
|
}
|
2019-01-02 19:22:01 +00:00
|
|
|
}
|
|
|
|
|
2019-01-14 18:49:53 +00:00
|
|
|
/// A volume that provides read access to its voxel data.
|
2019-01-02 19:22:01 +00:00
|
|
|
pub trait ReadVol: BaseVol {
|
2019-01-13 20:53:55 +00:00
|
|
|
/// Get a reference to the voxel at the provided position in the volume.
|
2019-01-02 19:22:01 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Err>;
|
2019-04-23 22:48:31 +00:00
|
|
|
|
|
|
|
fn ray(&self, from: Vec3<f32>, to: Vec3<f32>) -> Ray<Self, fn(&Self::Vox) -> bool>
|
|
|
|
where Self: Sized
|
|
|
|
{
|
|
|
|
Ray::new(self, from, to, |vox| !vox.is_empty())
|
|
|
|
}
|
2019-01-02 19:22:01 +00:00
|
|
|
}
|
|
|
|
|
2019-01-14 18:49:53 +00:00
|
|
|
/// A volume that provides the ability to sample (i.e: clone a section of) its voxel data.
|
|
|
|
pub trait SampleVol: BaseVol where Self::Vox: Clone {
|
|
|
|
type Sample: BaseVol + ReadVol;
|
|
|
|
/// Take a sample of the volume by cloning voxels within the provided range.
|
|
|
|
///
|
|
|
|
/// Note that value and accessibility of voxels outside the bounds of the sample is
|
|
|
|
/// implementation-defined and should not be used.
|
|
|
|
///
|
|
|
|
/// Note that the resultant volume has a coordinate space relative to the sample, not the
|
|
|
|
/// original volume.
|
|
|
|
fn sample(&self, range: Aabb<i32>) -> Result<Self::Sample, Self::Err>;
|
|
|
|
}
|
|
|
|
|
2019-01-13 20:53:55 +00:00
|
|
|
/// A volume that provides write access to its voxel data.
|
2019-01-02 19:22:01 +00:00
|
|
|
pub trait WriteVol: BaseVol {
|
2019-01-13 20:53:55 +00:00
|
|
|
/// Set the voxel at the provided position in the volume to the provided value.
|
2019-01-02 19:22:01 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn set(&mut self, pos: Vec3<i32>, vox: Self::Vox) -> Result<(), Self::Err>;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Utility traits
|
|
|
|
|
2019-01-13 20:53:55 +00:00
|
|
|
/// Used to specify a volume's compile-time size. This exists as a substitute until const generics
|
|
|
|
/// are implemented.
|
2019-01-02 19:22:01 +00:00
|
|
|
pub trait VolSize {
|
|
|
|
const SIZE: Vec3<u32>;
|
|
|
|
}
|