voxygen: Make the Terrain struct generic

This commit is contained in:
haslersn
2019-09-04 00:57:25 +02:00
parent 1796c09ca1
commit d99bef6803
2 changed files with 29 additions and 25 deletions

View File

@ -18,7 +18,11 @@ use crate::{
window::Event, window::Event,
}; };
use client::Client; use client::Client;
use common::{comp, terrain::BlockKind, vol::ReadVol}; use common::{
comp,
terrain::{BlockKind, TerrainChunk},
vol::ReadVol,
};
use specs::Join; use specs::Join;
use vek::*; use vek::*;
@ -45,7 +49,7 @@ pub struct Scene {
skybox: Skybox, skybox: Skybox,
postprocess: PostProcess, postprocess: PostProcess,
terrain: Terrain, terrain: Terrain<TerrainChunk>,
loaded_distance: f32, loaded_distance: f32,
figure_mgr: FigureMgr, figure_mgr: FigureMgr,

View File

@ -10,15 +10,15 @@ use client::Client;
use common::{ use common::{
assets, assets,
figure::Segment, figure::Segment,
terrain::{Block, BlockKind, TerrainChunkSize, TerrainGrid}, terrain::{Block, BlockKind},
vol::{ReadVol, RectVolSize, SampleVol, Vox}, vol::{BaseVol, ReadVol, RectRasterableVol, SampleVol, Vox},
volumes::vol_grid_2d::VolGrid2dError, volumes::vol_grid_2d::{VolGrid2d, VolGrid2dError},
}; };
use crossbeam::channel; use crossbeam::channel;
use dot_vox::DotVoxData; use dot_vox::DotVoxData;
use frustum_query::frustum::Frustum; use frustum_query::frustum::Frustum;
use hashbrown::HashMap; use hashbrown::HashMap;
use std::{f32, i32, ops::Mul, time::Duration}; use std::{f32, fmt::Debug, i32, marker::PhantomData, ops::Mul, time::Duration};
use vek::*; use vek::*;
struct TerrainChunk { struct TerrainChunk {
@ -135,11 +135,11 @@ fn sprite_config_for(kind: BlockKind) -> Option<SpriteConfig> {
} }
/// Function executed by worker threads dedicated to chunk meshing. /// Function executed by worker threads dedicated to chunk meshing.
fn mesh_worker( fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug>(
pos: Vec2<i32>, pos: Vec2<i32>,
z_bounds: (f32, f32), z_bounds: (f32, f32),
started_tick: u64, started_tick: u64,
volume: <TerrainGrid as SampleVol<Aabr<i32>>>::Sample, volume: <VolGrid2d<V> as SampleVol<Aabr<i32>>>::Sample,
range: Aabb<i32>, range: Aabb<i32>,
) -> MeshWorkerResponse { ) -> MeshWorkerResponse {
let (opaque_mesh, fluid_mesh) = volume.generate_mesh(range); let (opaque_mesh, fluid_mesh) = volume.generate_mesh(range);
@ -152,12 +152,11 @@ fn mesh_worker(
sprite_instances: { sprite_instances: {
let mut instances = HashMap::new(); let mut instances = HashMap::new();
for x in 0..TerrainChunkSize::RECT_SIZE.x as i32 { for x in 0..V::RECT_SIZE.x as i32 {
for y in 0..TerrainChunkSize::RECT_SIZE.y as i32 { for y in 0..V::RECT_SIZE.y as i32 {
for z in z_bounds.0 as i32..z_bounds.1 as i32 + 1 { for z in z_bounds.0 as i32..z_bounds.1 as i32 + 1 {
let wpos = Vec3::from( let wpos = Vec3::from(pos * V::RECT_SIZE.map(|e: u32| e as i32))
pos * Vec2::from(TerrainChunkSize::RECT_SIZE).map(|e: u32| e as i32), + Vec3::new(x, y, z);
) + Vec3::new(x, y, z);
let kind = volume.get(wpos).unwrap_or(&Block::empty()).kind(); let kind = volume.get(wpos).unwrap_or(&Block::empty()).kind();
@ -189,7 +188,7 @@ fn mesh_worker(
} }
} }
pub struct Terrain { pub struct Terrain<V: RectRasterableVol> {
chunks: HashMap<Vec2<i32>, TerrainChunk>, chunks: HashMap<Vec2<i32>, TerrainChunk>,
// The mpsc sender and receiver used for talking to meshing worker threads. // The mpsc sender and receiver used for talking to meshing worker threads.
@ -200,9 +199,11 @@ pub struct Terrain {
// GPU data // GPU data
sprite_models: HashMap<(BlockKind, usize), Model<SpritePipeline>>, sprite_models: HashMap<(BlockKind, usize), Model<SpritePipeline>>,
phantom: PhantomData<V>,
} }
impl Terrain { impl<V: RectRasterableVol> Terrain<V> {
pub fn new(renderer: &mut Renderer) -> Self { pub fn new(renderer: &mut Renderer) -> Self {
// Create a new mpsc (Multiple Produced, Single Consumer) pair for communicating with // Create a new mpsc (Multiple Produced, Single Consumer) pair for communicating with
// worker threads that are meshing chunks. // worker threads that are meshing chunks.
@ -597,6 +598,7 @@ impl Terrain {
] ]
.into_iter() .into_iter()
.collect(), .collect(),
phantom: PhantomData,
} }
} }
@ -728,10 +730,10 @@ impl Terrain {
let aabr = Aabr { let aabr = Aabr {
min: todo min: todo
.pos .pos
.map2(TerrainGrid::chunk_size(), |e, sz| e * sz as i32 - 1), .map2(VolGrid2d::<V>::chunk_size(), |e, sz| e * sz as i32 - 1),
max: todo max: todo.pos.map2(VolGrid2d::<V>::chunk_size(), |e, sz| {
.pos (e + 1) * sz as i32 + 1
.map2(TerrainGrid::chunk_size(), |e, sz| (e + 1) * sz as i32 + 1), }),
}; };
// Copy out the chunk data we need to perform the meshing. We do this by taking a // Copy out the chunk data we need to perform the meshing. We do this by taking a
@ -807,7 +809,7 @@ impl Terrain {
locals: renderer locals: renderer
.create_consts(&[TerrainLocals { .create_consts(&[TerrainLocals {
model_offs: Vec3::from( model_offs: Vec3::from(
response.pos.map2(TerrainGrid::chunk_size(), |e, sz| { response.pos.map2(VolGrid2d::<V>::chunk_size(), |e, sz| {
e as f32 * sz as f32 e as f32 * sz as f32
}), }),
) )
@ -836,7 +838,7 @@ impl Terrain {
); );
// Update chunk visibility // Update chunk visibility
let chunk_sz = TerrainChunkSize::RECT_SIZE.x as f32; let chunk_sz = V::RECT_SIZE.x as f32;
for (pos, chunk) in &mut self.chunks { for (pos, chunk) in &mut self.chunks {
let chunk_pos = pos.map(|e| e as f32 * chunk_sz); let chunk_pos = pos.map(|e| e as f32 * chunk_sz);
@ -886,10 +888,8 @@ impl Terrain {
if chunk.visible { if chunk.visible {
const SPRITE_RENDER_DISTANCE: f32 = 128.0; const SPRITE_RENDER_DISTANCE: f32 = 128.0;
let chunk_center = pos let chunk_center =
.map2(Vec2::from(TerrainChunkSize::RECT_SIZE), |e, sz: u32| { pos.map2(V::RECT_SIZE, |e, sz: u32| (e as f32 + 0.5) * sz as f32);
(e as f32 + 0.5) * sz as f32
});
if Vec2::from(focus_pos).distance_squared(chunk_center) if Vec2::from(focus_pos).distance_squared(chunk_center)
< SPRITE_RENDER_DISTANCE * SPRITE_RENDER_DISTANCE < SPRITE_RENDER_DISTANCE * SPRITE_RENDER_DISTANCE
{ {