veloren/common/src/volumes/chunk.rs

104 lines
2.5 KiB
Rust
Raw Normal View History

2019-01-02 19:22:01 +00:00
// Standard
use std::marker::PhantomData;
// Library
use vek::*;
use serde_derive::{Serialize, Deserialize};
2019-01-02 19:22:01 +00:00
// Local
use crate::vol::{
2019-01-14 18:49:53 +00:00
Vox,
2019-01-02 19:22:01 +00:00
BaseVol,
SizedVol,
ReadVol,
WriteVol,
VolSize,
};
#[derive(Debug)]
2019-01-02 19:22:01 +00:00
pub enum ChunkErr {
OutOfBounds,
}
/// A volume with dimensions known at compile-time.
2019-01-02 19:22:01 +00:00
// V = Voxel
// S = Size (replace when const generics are a thing)
// M = Metadata
#[derive(Debug, Clone, Serialize, Deserialize)]
2019-01-14 18:49:53 +00:00
pub struct Chunk<V: Vox, S: VolSize, M> {
2019-01-02 19:22:01 +00:00
vox: Vec<V>,
meta: M,
phantom: PhantomData<S>,
}
2019-01-14 18:49:53 +00:00
impl<V: Vox, S: VolSize, M> Chunk<V, S, M> {
/// Used to transform a voxel position in the volume into its corresponding index in the voxel
// array.
2019-01-02 19:22:01 +00:00
#[inline(always)]
fn idx_for(pos: Vec3<i32>) -> Option<usize> {
if
pos.map(|e| e >= 0).reduce_and() &&
pos.map2(S::SIZE, |e, lim| e < lim as i32).reduce_and()
{
Some((
pos.x * S::SIZE.y as i32 * S::SIZE.z as i32 +
pos.y * S::SIZE.z as i32 +
pos.z
) as usize)
} else {
None
}
}
}
2019-01-14 18:49:53 +00:00
impl<V: Vox, S: VolSize, M> BaseVol for Chunk<V, S, M> {
2019-01-02 19:22:01 +00:00
type Vox = V;
type Err = ChunkErr;
}
2019-01-14 18:49:53 +00:00
impl<V: Vox, S: VolSize, M> SizedVol for Chunk<V, S, M> {
#[inline(always)]
fn get_size(&self) -> Vec3<u32> { S::SIZE }
2019-01-02 19:22:01 +00:00
}
2019-01-14 18:49:53 +00:00
impl<V: Vox, S: VolSize, M> ReadVol for Chunk<V, S, M> {
2019-01-02 19:22:01 +00:00
#[inline(always)]
fn get(&self, pos: Vec3<i32>) -> Result<&V, ChunkErr> {
Self::idx_for(pos)
.and_then(|idx| self.vox.get(idx))
.ok_or(ChunkErr::OutOfBounds)
}
}
2019-01-14 18:49:53 +00:00
impl<V: Vox, S: VolSize, M> WriteVol for Chunk<V, S, M> {
2019-01-02 19:22:01 +00:00
#[inline(always)]
fn set(&mut self, pos: Vec3<i32>, vox: Self::Vox) -> Result<(), ChunkErr> {
Self::idx_for(pos)
.and_then(|idx| self.vox.get_mut(idx))
.map(|old_vox| *old_vox = vox)
.ok_or(ChunkErr::OutOfBounds)
}
}
2019-01-14 18:49:53 +00:00
impl<V: Vox + Clone, S: VolSize, M> Chunk<V, S, M> {
/// Create a new `Chunk` with the provided dimensions and all voxels filled with duplicates of
/// the provided voxel.
2019-01-02 19:22:01 +00:00
pub fn filled(vox: V, meta: M) -> Self {
Self {
vox: vec![vox; S::SIZE.product() as usize],
meta,
phantom: PhantomData,
}
}
/// Get a reference to the internal metadata.
2019-01-02 19:22:01 +00:00
pub fn metadata(&self) -> &M {
&self.meta
}
/// Get a mutable reference to the internal metadata.
2019-01-02 19:22:01 +00:00
pub fn metadata_mut(&mut self) -> &mut M {
&mut self.meta
}
}