mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added terrain sprite LoD
This commit is contained in:
parent
8a855ea423
commit
b2c8dc0806
@ -2,7 +2,7 @@ pub mod cell;
|
||||
pub mod mat_cell;
|
||||
pub use mat_cell::Material;
|
||||
|
||||
use self::{cell::Cell, mat_cell::MatCell};
|
||||
pub use self::{cell::Cell, mat_cell::MatCell};
|
||||
use crate::{
|
||||
vol::{IntoFullPosIterator, IntoFullVolIterator, ReadVol, SizedVol, Vox, WriteVol},
|
||||
volumes::dyna::Dyna,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::ray::Ray;
|
||||
use crate::{ray::Ray, volumes::scaled::Scaled};
|
||||
use std::fmt::Debug;
|
||||
use vek::*;
|
||||
|
||||
@ -24,6 +24,13 @@ pub trait Vox: Sized + Clone + PartialEq {
|
||||
pub trait BaseVol {
|
||||
type Vox: Vox;
|
||||
type Error: Debug;
|
||||
|
||||
fn scaled_by(&self, scale: Vec3<f32>) -> Scaled<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Scaled { inner: self, scale }
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementing `BaseVol` for any `&'a BaseVol` makes it possible to implement
|
||||
@ -159,6 +166,7 @@ where
|
||||
/// Unfortunately we can't just implement `IntoIterator` in this generic way
|
||||
/// because it's defined in another crate. That's actually the only reason why
|
||||
/// the trait `IntoFullVolIterator` exists.
|
||||
// TODO: See whether relaxed orphan rules permit this to be replaced now
|
||||
impl<'a, T: 'a + SizedVol> IntoFullVolIterator<'a> for &'a T
|
||||
where
|
||||
Self: IntoVolIterator<'a>,
|
||||
|
@ -1,4 +1,5 @@
|
||||
pub mod chunk;
|
||||
pub mod dyna;
|
||||
pub mod scaled;
|
||||
pub mod vol_grid_2d;
|
||||
pub mod vol_grid_3d;
|
||||
|
47
common/src/volumes/scaled.rs
Normal file
47
common/src/volumes/scaled.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use crate::vol::{BaseVol, ReadVol, SizedVol, Vox};
|
||||
use vek::*;
|
||||
|
||||
pub struct Scaled<'a, V> {
|
||||
pub inner: &'a V,
|
||||
pub scale: Vec3<f32>,
|
||||
}
|
||||
|
||||
impl<'a, V: BaseVol> BaseVol for Scaled<'a, V> {
|
||||
type Error = V::Error;
|
||||
type Vox = V::Vox;
|
||||
}
|
||||
|
||||
impl<'a, V: ReadVol> ReadVol for Scaled<'a, V> {
|
||||
#[inline(always)]
|
||||
fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Error> {
|
||||
let pos = pos.map2(self.scale, |e, scale| (e as f32 / scale).trunc() as i32);
|
||||
let search_size = (Vec3::one() / self.scale).map(|e: f32| e.ceil() as i32);
|
||||
(-search_size.x / 2..search_size.x / 2)
|
||||
.map(|i| {
|
||||
(-search_size.y / 2..search_size.y / 2).map(move |j| {
|
||||
(-search_size.z / 2..search_size.z / 2).map(move |k| Vec3::new(i, j, k))
|
||||
})
|
||||
})
|
||||
.flatten()
|
||||
.flatten()
|
||||
.map(|offs| self.inner.get(pos + offs))
|
||||
.find(|vox| vox.as_ref().map(|v| !v.is_empty()).unwrap_or(false))
|
||||
.unwrap_or_else(|| self.inner.get(pos))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V: SizedVol> SizedVol for Scaled<'a, V> {
|
||||
#[inline(always)]
|
||||
fn lower_bound(&self) -> Vec3<i32> {
|
||||
self.inner
|
||||
.lower_bound()
|
||||
.map2(self.scale, |e, scale| (e as f32 * scale).floor() as i32)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn upper_bound(&self) -> Vec3<i32> {
|
||||
self.inner
|
||||
.upper_bound()
|
||||
.map2(self.scale, |e, scale| (e as f32 * scale).floor() as i32)
|
||||
}
|
||||
}
|
@ -4,14 +4,14 @@ mod vol;
|
||||
|
||||
use crate::render::{self, Mesh};
|
||||
|
||||
pub trait Meshable<P: render::Pipeline, T: render::Pipeline> {
|
||||
pub trait Meshable<'a, P: render::Pipeline, T: render::Pipeline> {
|
||||
type Pipeline: render::Pipeline;
|
||||
type TranslucentPipeline: render::Pipeline;
|
||||
type Supplement;
|
||||
|
||||
// Generate meshes - one opaque, one translucent
|
||||
fn generate_mesh(
|
||||
&self,
|
||||
&'a self,
|
||||
supp: Self::Supplement,
|
||||
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>);
|
||||
}
|
||||
|
@ -3,27 +3,43 @@ use crate::{
|
||||
render::{self, FigurePipeline, Mesh, SpritePipeline},
|
||||
};
|
||||
use common::{
|
||||
figure::Segment,
|
||||
figure::Cell,
|
||||
util::{linear_to_srgb, srgb_to_linear},
|
||||
vol::{IntoFullVolIterator, ReadVol, Vox},
|
||||
vol::{BaseVol, ReadVol, SizedVol, Vox},
|
||||
};
|
||||
use vek::*;
|
||||
|
||||
type FigureVertex = <FigurePipeline as render::Pipeline>::Vertex;
|
||||
type SpriteVertex = <SpritePipeline as render::Pipeline>::Vertex;
|
||||
|
||||
impl Meshable<FigurePipeline, FigurePipeline> for Segment {
|
||||
impl<'a, V: 'a> Meshable<'a, FigurePipeline, FigurePipeline> for V
|
||||
where
|
||||
V: BaseVol<Vox = Cell> + ReadVol + SizedVol,
|
||||
/* TODO: Use VolIterator instead of manually iterating
|
||||
* &'a V: IntoVolIterator<'a> + IntoFullVolIterator<'a>,
|
||||
* &'a V: BaseVol<Vox=Cell>, */
|
||||
{
|
||||
type Pipeline = FigurePipeline;
|
||||
type Supplement = Vec3<f32>;
|
||||
type Supplement = (Vec3<f32>, Vec3<f32>);
|
||||
type TranslucentPipeline = FigurePipeline;
|
||||
|
||||
fn generate_mesh(
|
||||
&self,
|
||||
offs: Self::Supplement,
|
||||
&'a self,
|
||||
(offs, scale): Self::Supplement,
|
||||
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
||||
let mut mesh = Mesh::new();
|
||||
|
||||
for (pos, vox) in self.full_vol_iter() {
|
||||
let vol_iter = (self.lower_bound().x..self.upper_bound().x)
|
||||
.map(|i| {
|
||||
(self.lower_bound().y..self.upper_bound().y).map(move |j| {
|
||||
(self.lower_bound().z..self.upper_bound().z).map(move |k| Vec3::new(i, j, k))
|
||||
})
|
||||
})
|
||||
.flatten()
|
||||
.flatten()
|
||||
.map(|pos| (pos, self.get(pos).unwrap()));
|
||||
|
||||
for (pos, vox) in vol_iter {
|
||||
if let Some(col) = vox.get_color() {
|
||||
vol::push_vox_verts(
|
||||
&mut mesh,
|
||||
@ -32,7 +48,7 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
|
||||
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
||||
|origin, norm, col, light, ao| {
|
||||
FigureVertex::new(
|
||||
origin,
|
||||
origin * scale,
|
||||
norm,
|
||||
linear_to_srgb(srgb_to_linear(col) * light),
|
||||
ao,
|
||||
@ -62,18 +78,34 @@ impl Meshable<FigurePipeline, FigurePipeline> for Segment {
|
||||
}
|
||||
}
|
||||
|
||||
impl Meshable<SpritePipeline, SpritePipeline> for Segment {
|
||||
impl<'a, V: 'a> Meshable<'a, SpritePipeline, SpritePipeline> for V
|
||||
where
|
||||
V: BaseVol<Vox = Cell> + ReadVol + SizedVol,
|
||||
/* TODO: Use VolIterator instead of manually iterating
|
||||
* &'a V: IntoVolIterator<'a> + IntoFullVolIterator<'a>,
|
||||
* &'a V: BaseVol<Vox=Cell>, */
|
||||
{
|
||||
type Pipeline = SpritePipeline;
|
||||
type Supplement = Vec3<f32>;
|
||||
type Supplement = (Vec3<f32>, Vec3<f32>);
|
||||
type TranslucentPipeline = SpritePipeline;
|
||||
|
||||
fn generate_mesh(
|
||||
&self,
|
||||
offs: Self::Supplement,
|
||||
&'a self,
|
||||
(offs, scale): Self::Supplement,
|
||||
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
||||
let mut mesh = Mesh::new();
|
||||
|
||||
for (pos, vox) in self.full_vol_iter() {
|
||||
let vol_iter = (self.lower_bound().x..self.upper_bound().x)
|
||||
.map(|i| {
|
||||
(self.lower_bound().y..self.upper_bound().y).map(move |j| {
|
||||
(self.lower_bound().z..self.upper_bound().z).map(move |k| Vec3::new(i, j, k))
|
||||
})
|
||||
})
|
||||
.flatten()
|
||||
.flatten()
|
||||
.map(|pos| (pos, self.get(pos).unwrap()));
|
||||
|
||||
for (pos, vox) in vol_iter {
|
||||
if let Some(col) = vox.get_color() {
|
||||
vol::push_vox_verts(
|
||||
&mut mesh,
|
||||
@ -82,7 +114,7 @@ impl Meshable<SpritePipeline, SpritePipeline> for Segment {
|
||||
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
||||
|origin, norm, col, light, ao| {
|
||||
SpriteVertex::new(
|
||||
origin,
|
||||
origin * scale,
|
||||
norm,
|
||||
linear_to_srgb(srgb_to_linear(col) * light),
|
||||
ao,
|
||||
|
@ -198,15 +198,15 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>(
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeline, FluidPipeline>
|
||||
for VolGrid2d<V>
|
||||
impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
|
||||
Meshable<'a, TerrainPipeline, FluidPipeline> for VolGrid2d<V>
|
||||
{
|
||||
type Pipeline = TerrainPipeline;
|
||||
type Supplement = Aabb<i32>;
|
||||
type TranslucentPipeline = FluidPipeline;
|
||||
|
||||
fn generate_mesh(
|
||||
&self,
|
||||
&'a self,
|
||||
range: Self::Supplement,
|
||||
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
||||
let mut light = calc_light(range, self);
|
||||
|
@ -55,7 +55,7 @@ fn graceful_load_mat_segment_flipped(mesh_name: &str) -> MatSegment {
|
||||
}
|
||||
|
||||
fn generate_mesh(segment: &Segment, offset: Vec3<f32>) -> Mesh<FigurePipeline> {
|
||||
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(segment, offset).0
|
||||
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(segment, (offset, Vec3::one())).0
|
||||
}
|
||||
|
||||
pub fn load_mesh(mesh_name: &str, position: Vec3<f32>) -> Mesh<FigurePipeline> {
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user