mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added vox trait
This commit is contained in:
parent
c5a506dad2
commit
ae4f1ae2ea
@ -6,5 +6,6 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
specs = "0.14"
|
||||
shred = "0.7"
|
||||
vek = "0.9"
|
||||
dot_vox = "1.0"
|
||||
|
@ -1,6 +1,9 @@
|
||||
// Library
|
||||
use vek::*;
|
||||
|
||||
// Crate
|
||||
use crate::vol::Vox;
|
||||
|
||||
/// A type representing a single voxel in a figure
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Cell {
|
||||
@ -9,21 +12,10 @@ pub enum Cell {
|
||||
}
|
||||
|
||||
impl Cell {
|
||||
pub fn empty() -> Self {
|
||||
Cell::Empty
|
||||
}
|
||||
|
||||
pub fn new(rgb: Rgb<u8>) -> Self {
|
||||
Cell::Filled(rgb.into_array())
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
Cell::Filled(_) => false,
|
||||
Cell::Empty => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_color(&self) -> Option<Rgb<u8>> {
|
||||
match self {
|
||||
Cell::Filled(col) => Some(Rgb::from(*col)),
|
||||
@ -31,3 +23,16 @@ impl Cell {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Vox for Cell {
|
||||
fn empty() -> Self {
|
||||
Cell::Empty
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
Cell::Filled(_) => false,
|
||||
Cell::Empty => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use dot_vox::DotVoxData;
|
||||
|
||||
// Crate
|
||||
use crate::{
|
||||
vol::WriteVol,
|
||||
vol::{Vox, WriteVol},
|
||||
volumes::dyna::Dyna,
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@ use std::time::Duration;
|
||||
|
||||
// External
|
||||
use specs::World as EcsWorld;
|
||||
use shred::Fetch;
|
||||
|
||||
// Crate
|
||||
use crate::{
|
||||
@ -24,8 +25,6 @@ struct Tick(f64);
|
||||
/// things like entity components, terrain data, and global state like weather, time of day, etc.
|
||||
pub struct State {
|
||||
ecs_world: EcsWorld,
|
||||
terrain_map: TerrainMap,
|
||||
time: f64,
|
||||
}
|
||||
|
||||
impl State {
|
||||
@ -36,14 +35,13 @@ impl State {
|
||||
// Register resources used by the ECS
|
||||
ecs_world.add_resource(TimeOfDay(0.0));
|
||||
ecs_world.add_resource(Tick(0.0));
|
||||
ecs_world.add_resource(TerrainMap::new());
|
||||
|
||||
// Register common components with the state
|
||||
comp::register_local_components(&mut ecs_world);
|
||||
|
||||
Self {
|
||||
ecs_world,
|
||||
terrain_map: TerrainMap::new(),
|
||||
time: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +59,11 @@ impl State {
|
||||
self.ecs_world.read_resource::<Tick>().0
|
||||
}
|
||||
|
||||
/// Get a reference to this state's terrain.
|
||||
pub fn terrain<'a>(&'a self) -> Fetch<'a, TerrainMap> {
|
||||
self.ecs_world.read_resource::<TerrainMap>()
|
||||
}
|
||||
|
||||
/// Execute a single tick, simulating the game state by the given duration.
|
||||
pub fn tick(&mut self, dt: Duration) {
|
||||
// Change the time accordingly
|
||||
|
@ -1,5 +1,21 @@
|
||||
// Crate
|
||||
use crate::vol::Vox;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Block {
|
||||
kind: u8,
|
||||
color: [u8; 3],
|
||||
}
|
||||
|
||||
impl Vox for Block {
|
||||
fn empty() -> Self {
|
||||
Self {
|
||||
kind: 0,
|
||||
color: [0; 3],
|
||||
}
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.kind == 0
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,15 @@
|
||||
// Library
|
||||
use vek::*;
|
||||
|
||||
/// A voxel
|
||||
pub trait Vox {
|
||||
fn empty() -> Self;
|
||||
fn is_empty(&self) -> bool;
|
||||
}
|
||||
|
||||
/// A volume that contains voxel data.
|
||||
pub trait BaseVol {
|
||||
type Vox;
|
||||
type Vox: Vox;
|
||||
type Err;
|
||||
}
|
||||
|
||||
@ -53,13 +59,26 @@ pub trait SizedVol: BaseVol {
|
||||
}
|
||||
}
|
||||
|
||||
/// A volume that provided read access to its voxel data.
|
||||
/// A volume that provides read access to its voxel data.
|
||||
pub trait ReadVol: BaseVol {
|
||||
/// Get a reference to the voxel at the provided position in the volume.
|
||||
#[inline(always)]
|
||||
fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Err>;
|
||||
}
|
||||
|
||||
/// 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>;
|
||||
}
|
||||
|
||||
/// A volume that provides write access to its voxel data.
|
||||
pub trait WriteVol: BaseVol {
|
||||
/// Set the voxel at the provided position in the volume to the provided value.
|
||||
|
@ -6,6 +6,7 @@ use vek::*;
|
||||
|
||||
// Local
|
||||
use crate::vol::{
|
||||
Vox,
|
||||
BaseVol,
|
||||
SizedVol,
|
||||
ReadVol,
|
||||
@ -21,13 +22,13 @@ pub enum ChunkErr {
|
||||
// V = Voxel
|
||||
// S = Size (replace when const generics are a thing)
|
||||
// M = Metadata
|
||||
pub struct Chunk<V, S: VolSize, M> {
|
||||
pub struct Chunk<V: Vox, S: VolSize, M> {
|
||||
vox: Vec<V>,
|
||||
meta: M,
|
||||
phantom: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> Chunk<V, S, M> {
|
||||
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.
|
||||
#[inline(always)]
|
||||
@ -47,17 +48,17 @@ impl<V, S: VolSize, M> Chunk<V, S, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> BaseVol for Chunk<V, S, M> {
|
||||
impl<V: Vox, S: VolSize, M> BaseVol for Chunk<V, S, M> {
|
||||
type Vox = V;
|
||||
type Err = ChunkErr;
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> SizedVol for Chunk<V, S, M> {
|
||||
impl<V: Vox, S: VolSize, M> SizedVol for Chunk<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn get_size(&self) -> Vec3<u32> { S::SIZE }
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> ReadVol for Chunk<V, S, M> {
|
||||
impl<V: Vox, S: VolSize, M> ReadVol for Chunk<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn get(&self, pos: Vec3<i32>) -> Result<&V, ChunkErr> {
|
||||
Self::idx_for(pos)
|
||||
@ -66,7 +67,7 @@ impl<V, S: VolSize, M> ReadVol for Chunk<V, S, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> WriteVol for Chunk<V, S, M> {
|
||||
impl<V: Vox, S: VolSize, M> WriteVol for Chunk<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn set(&mut self, pos: Vec3<i32>, vox: Self::Vox) -> Result<(), ChunkErr> {
|
||||
Self::idx_for(pos)
|
||||
@ -76,7 +77,7 @@ impl<V, S: VolSize, M> WriteVol for Chunk<V, S, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Clone, S: VolSize, M> Chunk<V, S, M> {
|
||||
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.
|
||||
pub fn filled(vox: V, meta: M) -> Self {
|
||||
|
@ -3,6 +3,7 @@ use vek::*;
|
||||
|
||||
// Local
|
||||
use crate::vol::{
|
||||
Vox,
|
||||
BaseVol,
|
||||
SizedVol,
|
||||
ReadVol,
|
||||
@ -17,13 +18,13 @@ pub enum DynaErr {
|
||||
// V = Voxel
|
||||
// S = Size (replace when const generics are a thing)
|
||||
// M = Metadata
|
||||
pub struct Dyna<V, M> {
|
||||
pub struct Dyna<V: Vox, M> {
|
||||
vox: Vec<V>,
|
||||
meta: M,
|
||||
sz: Vec3<u32>,
|
||||
}
|
||||
|
||||
impl<V, M> Dyna<V, M> {
|
||||
impl<V: Vox, M> Dyna<V, M> {
|
||||
/// Used to transform a voxel position in the volume into its corresponding index in the voxel
|
||||
// array.
|
||||
#[inline(always)]
|
||||
@ -43,17 +44,17 @@ impl<V, M> Dyna<V, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, M> BaseVol for Dyna<V, M> {
|
||||
impl<V: Vox, M> BaseVol for Dyna<V, M> {
|
||||
type Vox = V;
|
||||
type Err = DynaErr;
|
||||
}
|
||||
|
||||
impl<V, M> SizedVol for Dyna<V, M> {
|
||||
impl<V: Vox, M> SizedVol for Dyna<V, M> {
|
||||
#[inline(always)]
|
||||
fn get_size(&self) -> Vec3<u32> { self.sz }
|
||||
}
|
||||
|
||||
impl<V, M> ReadVol for Dyna<V, M> {
|
||||
impl<V: Vox, M> ReadVol for Dyna<V, M> {
|
||||
#[inline(always)]
|
||||
fn get(&self, pos: Vec3<i32>) -> Result<&V, DynaErr> {
|
||||
Self::idx_for(self.sz, pos)
|
||||
@ -62,7 +63,7 @@ impl<V, M> ReadVol for Dyna<V, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, M> WriteVol for Dyna<V, M> {
|
||||
impl<V: Vox, M> WriteVol for Dyna<V, M> {
|
||||
#[inline(always)]
|
||||
fn set(&mut self, pos: Vec3<i32>, vox: Self::Vox) -> Result<(), DynaErr> {
|
||||
Self::idx_for(self.sz, pos)
|
||||
@ -72,7 +73,7 @@ impl<V, M> WriteVol for Dyna<V, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Clone, M> Dyna<V, M> {
|
||||
impl<V: Vox + Clone, M> Dyna<V, M> {
|
||||
/// 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 {
|
||||
|
@ -7,27 +7,34 @@ use vek::*;
|
||||
// Crate
|
||||
use crate::{
|
||||
vol::{
|
||||
Vox,
|
||||
BaseVol,
|
||||
SizedVol,
|
||||
ReadVol,
|
||||
SampleVol,
|
||||
WriteVol,
|
||||
VolSize,
|
||||
},
|
||||
volumes::chunk::{Chunk, ChunkErr},
|
||||
volumes::{
|
||||
chunk::{Chunk, ChunkErr},
|
||||
dyna::{Dyna, DynaErr},
|
||||
},
|
||||
};
|
||||
|
||||
pub enum VolMapErr {
|
||||
NoSuchChunk,
|
||||
ChunkErr(ChunkErr),
|
||||
DynaErr(DynaErr),
|
||||
}
|
||||
|
||||
// V = Voxel
|
||||
// S = Size (replace with a const when const generics is a thing)
|
||||
// M = Chunk metadata
|
||||
pub struct VolMap<V, S: VolSize, M> {
|
||||
pub struct VolMap<V: Vox, S: VolSize, M> {
|
||||
chunks: HashMap<Vec3<i32>, Chunk<V, S, M>>,
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> VolMap<V, S, M> {
|
||||
impl<V: Vox, S: VolSize, M> VolMap<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn chunk_key(pos: Vec3<i32>) -> Vec3<i32> {
|
||||
pos.map2(S::SIZE, |e, sz| e.div_euclid(sz as i32))
|
||||
@ -39,12 +46,12 @@ impl<V, S: VolSize, M> VolMap<V, S, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> BaseVol for VolMap<V, S, M> {
|
||||
impl<V: Vox, S: VolSize, M> BaseVol for VolMap<V, S, M> {
|
||||
type Vox = V;
|
||||
type Err = VolMapErr;
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> ReadVol for VolMap<V, S, M> {
|
||||
impl<V: Vox, S: VolSize, M> ReadVol for VolMap<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn get(&self, pos: Vec3<i32>) -> Result<&V, VolMapErr> {
|
||||
let ck = Self::chunk_key(pos);
|
||||
@ -57,7 +64,29 @@ impl<V, S: VolSize, M> ReadVol for VolMap<V, S, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> WriteVol for VolMap<V, S, M> {
|
||||
impl<V: Vox + Clone, S: VolSize, M> SampleVol for VolMap<V, S, M> {
|
||||
type Sample = Dyna<V, ()>;
|
||||
|
||||
/// Take a sample of the terrain by cloning the voxels within the provided range.
|
||||
///
|
||||
/// Note that the resultant volume does not carry forward metadata from the original chunks.
|
||||
fn sample(&self, range: Aabb<i32>) -> Result<Self::Sample, VolMapErr> {
|
||||
let mut sample = Dyna::filled(
|
||||
range.size().map(|e| e as u32).into(),
|
||||
V::empty(),
|
||||
(),
|
||||
);
|
||||
|
||||
for pos in sample.iter_positions() {
|
||||
sample.set(pos, self.get(range.min + pos)?.clone())
|
||||
.map_err(|err| VolMapErr::DynaErr(err))?;
|
||||
}
|
||||
|
||||
Ok(sample)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Vox, S: VolSize, M> WriteVol for VolMap<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn set(&mut self, pos: Vec3<i32>, vox: V) -> Result<(), VolMapErr> {
|
||||
let ck = Self::chunk_key(pos);
|
||||
@ -70,7 +99,7 @@ impl<V, S: VolSize, M> WriteVol for VolMap<V, S, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> VolMap<V, S, M> {
|
||||
impl<V: Vox, S: VolSize, M> VolMap<V, S, M> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
chunks: HashMap::new(),
|
||||
|
@ -16,7 +16,7 @@ pub struct CharacterSkeleton {
|
||||
head: Bone,
|
||||
chest: Bone,
|
||||
belt: Bone,
|
||||
leggings: Bone,
|
||||
shorts: Bone,
|
||||
l_hand: Bone,
|
||||
r_hand: Bone,
|
||||
l_foot: Bone,
|
||||
@ -30,7 +30,7 @@ impl CharacterSkeleton {
|
||||
head: Bone::default(),
|
||||
chest: Bone::default(),
|
||||
belt: Bone::default(),
|
||||
leggings: Bone::default(),
|
||||
shorts: Bone::default(),
|
||||
l_hand: Bone::default(),
|
||||
r_hand: Bone::default(),
|
||||
l_foot: Bone::default(),
|
||||
@ -48,7 +48,7 @@ impl Skeleton for CharacterSkeleton {
|
||||
FigureBoneData::new(self.head.compute_base_matrix()),
|
||||
FigureBoneData::new(chest_mat),
|
||||
FigureBoneData::new(self.belt.compute_base_matrix()),
|
||||
FigureBoneData::new(self.leggings.compute_base_matrix()),
|
||||
FigureBoneData::new(self.shorts.compute_base_matrix()),
|
||||
FigureBoneData::new(self.l_hand.compute_base_matrix()),
|
||||
FigureBoneData::new(self.r_hand.compute_base_matrix()),
|
||||
FigureBoneData::new(self.l_foot.compute_base_matrix()),
|
||||
|
@ -29,8 +29,8 @@ impl Animation for RunAnimation {
|
||||
skeleton.belt.offset = Vec3::unit_z() * 7.0;
|
||||
skeleton.belt.ori = Quaternion::rotation_z(wave * 0.3);
|
||||
|
||||
skeleton.leggings.offset = Vec3::unit_z() * 4.0;
|
||||
skeleton.leggings.ori = Quaternion::rotation_z(wave * 0.3);
|
||||
skeleton.shorts.offset = Vec3::unit_z() * 4.0;
|
||||
skeleton.shorts.ori = Quaternion::rotation_z(wave * 0.3);
|
||||
|
||||
skeleton.l_hand.offset = Vec3::new(-8.0, wave * 5.0, 9.0);
|
||||
skeleton.r_hand.offset = Vec3::new(8.0, -wave * 5.0, 9.0);
|
||||
|
@ -6,6 +6,7 @@ use vek::*;
|
||||
|
||||
// Project
|
||||
use common::vol::{
|
||||
Vox,
|
||||
SizedVol,
|
||||
ReadVol,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user