2019-01-13 20:53:55 +00:00
|
|
|
// Library
|
2019-05-24 12:25:31 +00:00
|
|
|
use serde_derive::{Deserialize, Serialize};
|
2019-05-25 05:54:47 +00:00
|
|
|
use vek::*;
|
2019-01-13 20:53:55 +00:00
|
|
|
|
|
|
|
// Local
|
2019-04-29 20:37:19 +00:00
|
|
|
use crate::vol::{BaseVol, ReadVol, SizedVol, Vox, WriteVol};
|
2019-01-13 20:53:55 +00:00
|
|
|
|
2019-01-23 22:21:47 +00:00
|
|
|
#[derive(Debug)]
|
2019-01-13 20:53:55 +00:00
|
|
|
pub enum DynaErr {
|
|
|
|
OutOfBounds,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A volume with dimensions known only at the creation of the object.
|
|
|
|
// V = Voxel
|
|
|
|
// S = Size (replace when const generics are a thing)
|
|
|
|
// M = Metadata
|
2019-05-24 12:25:31 +00:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
2019-01-14 18:49:53 +00:00
|
|
|
pub struct Dyna<V: Vox, M> {
|
2019-01-13 20:53:55 +00:00
|
|
|
vox: Vec<V>,
|
|
|
|
meta: M,
|
|
|
|
sz: Vec3<u32>,
|
|
|
|
}
|
|
|
|
|
2019-01-14 18:49:53 +00:00
|
|
|
impl<V: Vox, M> Dyna<V, M> {
|
2019-05-17 09:22:32 +00:00
|
|
|
/// Used to transform a voxel position in the volume into its corresponding index
|
|
|
|
/// in the voxel array.
|
2019-01-13 20:53:55 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn idx_for(sz: Vec3<u32>, pos: Vec3<i32>) -> Option<usize> {
|
2019-04-29 20:37:19 +00:00
|
|
|
if pos.map(|e| e >= 0).reduce_and() && pos.map2(sz, |e, lim| e < lim as i32).reduce_and() {
|
2019-06-06 06:42:59 +00:00
|
|
|
Some(Self::idx_for_unchecked(sz, pos))
|
2019-01-13 20:53:55 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2019-06-05 15:22:06 +00:00
|
|
|
|
|
|
|
/// Used to transform a voxel position in the volume into its corresponding index
|
|
|
|
/// in the voxel array.
|
|
|
|
#[inline(always)]
|
|
|
|
fn idx_for_unchecked(sz: Vec3<u32>, pos: Vec3<i32>) -> usize {
|
|
|
|
(pos.x * sz.y as i32 * sz.z as i32 + pos.y * sz.z as i32 + pos.z) as usize
|
|
|
|
}
|
2019-01-13 20:53:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-14 18:49:53 +00:00
|
|
|
impl<V: Vox, M> BaseVol for Dyna<V, M> {
|
2019-01-13 20:53:55 +00:00
|
|
|
type Vox = V;
|
|
|
|
type Err = DynaErr;
|
|
|
|
}
|
|
|
|
|
2019-01-14 18:49:53 +00:00
|
|
|
impl<V: Vox, M> SizedVol for Dyna<V, M> {
|
2019-01-13 20:53:55 +00:00
|
|
|
#[inline(always)]
|
2019-04-29 20:37:19 +00:00
|
|
|
fn get_size(&self) -> Vec3<u32> {
|
|
|
|
self.sz
|
|
|
|
}
|
2019-01-13 20:53:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-14 18:49:53 +00:00
|
|
|
impl<V: Vox, M> ReadVol for Dyna<V, M> {
|
2019-01-13 20:53:55 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn get(&self, pos: Vec3<i32>) -> Result<&V, DynaErr> {
|
|
|
|
Self::idx_for(self.sz, pos)
|
|
|
|
.and_then(|idx| self.vox.get(idx))
|
|
|
|
.ok_or(DynaErr::OutOfBounds)
|
|
|
|
}
|
2019-06-05 15:22:06 +00:00
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
unsafe fn get_unchecked(&self, pos: Vec3<i32>) -> &V {
|
|
|
|
self.vox
|
|
|
|
.get_unchecked(Self::idx_for_unchecked(self.sz, pos))
|
|
|
|
}
|
2019-01-13 20:53:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-14 18:49:53 +00:00
|
|
|
impl<V: Vox, M> WriteVol for Dyna<V, M> {
|
2019-01-13 20:53:55 +00:00
|
|
|
#[inline(always)]
|
|
|
|
fn set(&mut self, pos: Vec3<i32>, vox: Self::Vox) -> Result<(), DynaErr> {
|
|
|
|
Self::idx_for(self.sz, pos)
|
|
|
|
.and_then(|idx| self.vox.get_mut(idx))
|
|
|
|
.map(|old_vox| *old_vox = vox)
|
|
|
|
.ok_or(DynaErr::OutOfBounds)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-14 18:49:53 +00:00
|
|
|
impl<V: Vox + Clone, M> Dyna<V, M> {
|
2019-01-13 20:53:55 +00:00
|
|
|
/// Create a new `Dyna` with the provided dimensions and all voxels filled with duplicates of
|
|
|
|
/// the provided voxel.
|
|
|
|
pub fn filled(sz: Vec3<u32>, vox: V, meta: M) -> Self {
|
|
|
|
Self {
|
|
|
|
vox: vec![vox; sz.product() as usize],
|
|
|
|
meta,
|
|
|
|
sz,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get a reference to the internal metadata.
|
|
|
|
pub fn metadata(&self) -> &M {
|
|
|
|
&self.meta
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get a mutable reference to the internal metadata.
|
|
|
|
pub fn metadata_mut(&mut self) -> &mut M {
|
|
|
|
&mut self.meta
|
|
|
|
}
|
|
|
|
}
|