mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Small fix to executor scheduling.
Also some preliminary separation for new lighting and removal of some unneeded checks.
This commit is contained in:
parent
8d9680c68b
commit
0c99438993
@ -13,7 +13,7 @@ use executors::{
|
|||||||
parker::{LargeThreadData, StaticParker},
|
parker::{LargeThreadData, StaticParker},
|
||||||
Executor,
|
Executor,
|
||||||
};
|
};
|
||||||
pub use executors::{builder::ThreadPoolBuilder, parker::large};
|
pub use executors::{builder::ThreadPoolBuilder, parker::large, FuturesExecutor};
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
// use rayon::ThreadPool;
|
// use rayon::ThreadPool;
|
||||||
@ -515,7 +515,7 @@ impl SlowJobPool {
|
|||||||
|
|
||||||
// NOTE: It's important not to use internal until we're in the spawned thread, since the
|
// NOTE: It's important not to use internal until we're in the spawned thread, since the
|
||||||
// lock is probably currently taken!
|
// lock is probably currently taken!
|
||||||
self.threadpool.execute(move || {
|
self.threadpool./*execute*/spawn(async move {
|
||||||
// Repeatedly run until exit; we do things this way to avoid recursion, which might blow
|
// Repeatedly run until exit; we do things this way to avoid recursion, which might blow
|
||||||
// our call stack.
|
// our call stack.
|
||||||
loop {
|
loop {
|
||||||
@ -549,6 +549,19 @@ impl SlowJobPool {
|
|||||||
execution_start,
|
execution_start,
|
||||||
execution_end,
|
execution_end,
|
||||||
};
|
};
|
||||||
|
// Hint to the scheduler to run any tasks that were explicitly woken. This should
|
||||||
|
// run explicitly-woken tasks first (if enough time has elapsed, including tasks
|
||||||
|
// woken by other threads). Waiting to acquire the next job until we've yielded
|
||||||
|
// also gives other threads the opportunity to take any queued-up slowjobs.
|
||||||
|
tokio::task::yield_now().await;
|
||||||
|
// Hint to scheduler to run any other threads that are currently waiting, since
|
||||||
|
// slowjobs are, well, slow! i.e. the cost of yielding should be very small
|
||||||
|
// compared to the cost of actually running the job for *almost* every job on the
|
||||||
|
// pool (and for jobs for which this isn't true, we should probably batch them up).
|
||||||
|
//
|
||||||
|
// NOTE: Ideally this would be done automatically as part of the yield, but
|
||||||
|
// async_executor currently isn't a very good citizen in this regard.
|
||||||
|
std::thread::yield_now();
|
||||||
// directly maintain the next task afterwards
|
// directly maintain the next task afterwards
|
||||||
let next_task = {
|
let next_task = {
|
||||||
// We take the lock in this scope to make sure it's dropped before we
|
// We take the lock in this scope to make sure it's dropped before we
|
||||||
@ -569,13 +582,8 @@ impl SlowJobPool {
|
|||||||
// times or something in case we have more tasks to execute).
|
// times or something in case we have more tasks to execute).
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
// Hint to scheduler to run any other threads that are currently waiting, since
|
|
||||||
// slowjobs are, well, slow :) i.e. the cost of yielding should be very small
|
|
||||||
// compared to the cost of actually running the job for *almost* every job on the
|
|
||||||
// pool (and for jobs for which this isn't true, we should probably batch them up).
|
|
||||||
std::thread::yield_now();
|
|
||||||
}
|
}
|
||||||
});
|
}).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// spawn a new slow job on a certain NAME IF it can run immediately
|
/// spawn a new slow job on a certain NAME IF it can run immediately
|
||||||
|
@ -71,8 +71,57 @@ fn flat_get<'a>(flat: &'a Vec<Block>, w: i32, h: i32, d: i32) -> impl Fn(Vec3<i3
|
|||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UNKNOWN: u8 = 255;
|
||||||
|
|
||||||
|
struct LightMap {
|
||||||
|
default_light: u8,
|
||||||
|
bounds: Aabb<i32>,
|
||||||
|
light_map: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LightMap {
|
||||||
|
fn into_fn(self) -> impl Fn(Vec3<i32>) -> f32 + 'static + Send + Sync {
|
||||||
|
let outer = Aabb {
|
||||||
|
min: self.bounds.min/* - Vec3::new(SUNLIGHT as i32, SUNLIGHT as i32, 1) */ - Vec3::new(0, 0, 1),
|
||||||
|
max: self.bounds.max/* + Vec3::new(SUNLIGHT as i32, SUNLIGHT as i32, 1) */ + Vec3::new(0, 0, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* let mut vol_cached = vol.cached(); */
|
||||||
|
|
||||||
|
let mut light_map_ = vec![UNKNOWN; outer.size().product() as usize];
|
||||||
|
let (w_, h_, d_) = outer.clone().size().into_tuple();
|
||||||
|
let wh_ = w_ * h_;
|
||||||
|
|
||||||
|
let lm_idx = {
|
||||||
|
#[inline(always)] move |x, y, z| {
|
||||||
|
(wh_ * z + w_ * y + x) as usize
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let min_bounds = Aabb {
|
||||||
|
min: self.bounds.min - Vec3::unit_z(),
|
||||||
|
max: self.bounds.max + Vec3::unit_z(),
|
||||||
|
};
|
||||||
|
|
||||||
|
#[inline(always)] move |wpos| {
|
||||||
|
/* if is_sunlight { return 1.0 } else { 0.0 } */
|
||||||
|
let pos = wpos - min_bounds.min;
|
||||||
|
let l = self.light_map
|
||||||
|
.get(/*lm_idx2*/lm_idx(pos.x, pos.y, pos.z))
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(if pos.z < 0 { 0 } else { self.default_light });
|
||||||
|
|
||||||
|
if /* l != OPAQUE && */l != UNKNOWN {
|
||||||
|
l as f32 * SUNLIGHT_INV
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn calc_light<'a,
|
fn calc_light<'a,
|
||||||
V: RectRasterableVol<Vox = Block> + ReadVol + Debug + 'static,
|
/* V: RectRasterableVol<Vox = Block> + ReadVol + Debug + 'static, */
|
||||||
I: Iterator<Item=(Vec3<i32>, u8)>,
|
I: Iterator<Item=(Vec3<i32>, u8)>,
|
||||||
/* F: /*for<'x> */for<'a> fn(&'a Vec<Block>) -> G, */
|
/* F: /*for<'x> */for<'a> fn(&'a Vec<Block>) -> G, */
|
||||||
/* G: /*[&'x &'a (); 0], */Fn(Vec3<i32>) -> Block, */
|
/* G: /*[&'x &'a (); 0], */Fn(Vec3<i32>) -> Block, */
|
||||||
@ -82,13 +131,12 @@ fn calc_light<'a,
|
|||||||
default_light: u8,
|
default_light: u8,
|
||||||
bounds: Aabb<i32>,
|
bounds: Aabb<i32>,
|
||||||
range: Aabb<i32>,
|
range: Aabb<i32>,
|
||||||
vol: &'a VolGrid2d<V>,
|
/* vol: &'a VolGrid2d<V>, */
|
||||||
lit_blocks: I,
|
lit_blocks: I,
|
||||||
flat: &'a Vec<Block>,
|
flat: &'a Vec<Block>,
|
||||||
(w, h, d): (i32, i32, i32)
|
(w, h, d): (i32, i32, i32)
|
||||||
) -> impl Fn(Vec3<i32>) -> f32 + 'static + Send + Sync/*CalcLightFn*//*<V, I>*/ {
|
) -> /*impl Fn(Vec3<i32>) -> f32 + 'static + Send + Sync/*CalcLightFn*//*<V, I>*/*/LightMap {
|
||||||
span!(_guard, "calc_light");
|
span!(_guard, "calc_light");
|
||||||
const UNKNOWN: u8 = 255;
|
|
||||||
const OPAQUE: u8 = 254;
|
const OPAQUE: u8 = 254;
|
||||||
|
|
||||||
let outer = Aabb {
|
let outer = Aabb {
|
||||||
@ -295,7 +343,7 @@ fn calc_light<'a,
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let min_bounds = Aabb {
|
/* let min_bounds = Aabb {
|
||||||
min: bounds.min - Vec3::unit_z(),
|
min: bounds.min - Vec3::unit_z(),
|
||||||
max: bounds.max + Vec3::unit_z(),
|
max: bounds.max + Vec3::unit_z(),
|
||||||
};
|
};
|
||||||
@ -332,31 +380,47 @@ fn calc_light<'a,
|
|||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
|
} */
|
||||||
|
LightMap {
|
||||||
|
default_light,
|
||||||
|
bounds,
|
||||||
|
light_map: light_map_,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type V = TerrainChunk;
|
type V = TerrainChunk;
|
||||||
|
|
||||||
#[tracing::instrument(skip_all, name = "<&VolGrid2d as Meshable<_, _>>::generate_mesh")]
|
pub struct PreparedLights {
|
||||||
|
flat: Vec<Block>,
|
||||||
|
row_kinds: Vec<u8>,
|
||||||
|
z_start: i32,
|
||||||
|
z_end: i32,
|
||||||
|
light: LightMap,
|
||||||
|
glow: LightMap,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Representative block for air.
|
||||||
|
const AIR: Block = Block::air(common::terrain::sprite::SpriteKind::Empty);
|
||||||
|
/// Representative block for liquid.
|
||||||
|
///
|
||||||
|
/// FIXME: Can you really skip meshing for general liquids? Probably not...
|
||||||
|
const LIQUID: Block = Block::water(common::terrain::sprite::SpriteKind::Empty);
|
||||||
|
/// Representtive block for solids.
|
||||||
|
///
|
||||||
|
/// FIXME: Really hacky!
|
||||||
|
const OPAQUE: Block = Block::lava(common::terrain::sprite::SpriteKind::Empty);
|
||||||
|
|
||||||
|
const ALL_OPAQUE: u8 = 0b1;
|
||||||
|
const ALL_LIQUID: u8 = 0b10;
|
||||||
|
const ALL_AIR: u8 = 0b100;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all, name = "<&VolGrid2d as Meshable<_, _>>::prepare_lights")]
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub async fn generate_mesh<'a, F: Future<Output=Option<Model<[u8; 4]>>> + 'a>(
|
pub fn prepare_lights(
|
||||||
vol: &'a VolGrid2d<V>,
|
vol: &VolGrid2d<V>,
|
||||||
create_texture: impl FnOnce(usize) -> /*Option<Model<[u8; 4]>>*/F + Send,
|
(range, boi): (Aabb<i32>, &BlocksOfInterest),
|
||||||
(range, max_texture_size, boi): (Aabb<i32>, Vec2<u16>, &'a BlocksOfInterest),
|
) -> PreparedLights {
|
||||||
) -> MeshGen<
|
|
||||||
TerrainVertex,
|
|
||||||
FluidVertex,
|
|
||||||
TerrainVertex,
|
|
||||||
(
|
|
||||||
Aabb<f32>,
|
|
||||||
/*ColLightInfo*/(Option<Model<[u8; 4]>>, Vec2<u16>),
|
|
||||||
Arc<dyn Fn(Vec3<i32>) -> f32 + Send + Sync>,
|
|
||||||
Arc<dyn Fn(Vec3<i32>) -> f32 + Send + Sync>,
|
|
||||||
AltIndices,
|
|
||||||
(f32, f32),
|
|
||||||
),
|
|
||||||
> {
|
|
||||||
/* span!(
|
/* span!(
|
||||||
_guard,
|
_guard,
|
||||||
"generate_mesh",
|
"generate_mesh",
|
||||||
@ -374,20 +438,6 @@ pub async fn generate_mesh<'a, F: Future<Output=Option<Model<[u8; 4]>>> + 'a>(
|
|||||||
// z can range from -1..range.size().d + 1
|
// z can range from -1..range.size().d + 1
|
||||||
let d = d + 2;
|
let d = d + 2;
|
||||||
|
|
||||||
/// Representative block for air.
|
|
||||||
const AIR: Block = Block::air(common::terrain::sprite::SpriteKind::Empty);
|
|
||||||
/// Representative block for liquid.
|
|
||||||
///
|
|
||||||
/// FIXME: Can you really skip meshing for general liquids? Probably not...
|
|
||||||
const LIQUID: Block = Block::water(common::terrain::sprite::SpriteKind::Empty);
|
|
||||||
/// Representtive block for solids.
|
|
||||||
///
|
|
||||||
/// FIXME: Really hacky!
|
|
||||||
const OPAQUE: Block = Block::lava(common::terrain::sprite::SpriteKind::Empty);
|
|
||||||
|
|
||||||
const ALL_OPAQUE: u8 = 0b1;
|
|
||||||
const ALL_LIQUID: u8 = 0b10;
|
|
||||||
const ALL_AIR: u8 = 0b100;
|
|
||||||
// For each horizontal slice of the chunk, we keep track of what kinds of blocks are in it.
|
// For each horizontal slice of the chunk, we keep track of what kinds of blocks are in it.
|
||||||
// This allows us to compute limits after the fact, much more precisely than keeping track of a
|
// This allows us to compute limits after the fact, much more precisely than keeping track of a
|
||||||
// single intersection would; it also lets us skip homogeoneous slices entirely.
|
// single intersection would; it also lets us skip homogeoneous slices entirely.
|
||||||
@ -652,6 +702,7 @@ pub async fn generate_mesh<'a, F: Future<Output=Option<Model<[u8; 4]>>> + 'a>(
|
|||||||
let z_max = chonk.get_max_z() - chonk.get_min_z();
|
let z_max = chonk.get_max_z() - chonk.get_min_z();
|
||||||
let below = *chonk.below();
|
let below = *chonk.below();
|
||||||
|
|
||||||
|
// FIXME: This copies way more groups than necessary for side and corner chunks.
|
||||||
let flat_chunk = chonk.make_flat(&arena);
|
let flat_chunk = chonk.make_flat(&arena);
|
||||||
|
|
||||||
let min_z_ = z_diff - intersection.min.z;
|
let min_z_ = z_diff - intersection.min.z;
|
||||||
@ -665,6 +716,8 @@ pub async fn generate_mesh<'a, F: Future<Output=Option<Model<[u8; 4]>>> + 'a>(
|
|||||||
ALL_AIR
|
ALL_AIR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// chonk.min.z - flat_range.min.z = chonk.min.z - (range.min.z - 1)
|
||||||
|
// NOTE: max(0) should not be required when this is fixed to work properly.
|
||||||
let skip_count = min_z_.max(0);
|
let skip_count = min_z_.max(0);
|
||||||
let take_count = (max_z_.min(d) - skip_count).max(0);
|
let take_count = (max_z_.min(d) - skip_count).max(0);
|
||||||
let skip_count = skip_count as usize;
|
let skip_count = skip_count as usize;
|
||||||
@ -793,7 +846,7 @@ pub async fn generate_mesh<'a, F: Future<Output=Option<Model<[u8; 4]>>> + 'a>(
|
|||||||
light_end = Some(z);
|
light_end = Some(z);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// We could probably handle mixed opaque/liquid a well, since it's pretty much guaranteed
|
// We could probably handle mixed opaque/liquid as well, since it's pretty much guaranteed
|
||||||
// to attenuate, but we choose not to since we expect this to be much more
|
// to attenuate, but we choose not to since we expect this to be much more
|
||||||
// common than fully opaque chunks.
|
// common than fully opaque chunks.
|
||||||
_ => {},
|
_ => {},
|
||||||
@ -896,8 +949,54 @@ pub async fn generate_mesh<'a, F: Future<Output=Option<Model<[u8; 4]>>> + 'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
let light = calc_light(true, SUNLIGHT, light_range, range, vol, core::iter::empty(), &flat, (w, h, d));
|
let light = calc_light(true, SUNLIGHT, light_range, range/*, vol*/, core::iter::empty(), &flat, (w, h, d));
|
||||||
let glow = calc_light(false, 0, glow_range, range, vol, glow_blocks.into_iter(), &flat, (w, h, d));
|
let glow = calc_light(false, 0, glow_range, range/*, vol*/, glow_blocks.into_iter(), &flat, (w, h, d));
|
||||||
|
|
||||||
|
PreparedLights {
|
||||||
|
flat,
|
||||||
|
row_kinds,
|
||||||
|
z_start,
|
||||||
|
z_end,
|
||||||
|
light,
|
||||||
|
glow,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all, name = "<&VolGrid2d as Meshable<_, _>>::generate_mesh")]
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
#[inline(always)]
|
||||||
|
pub async fn generate_mesh<'a, F: Future<Output=Option<Model<[u8; 4]>>> + 'a>(
|
||||||
|
vol: &'a VolGrid2d<V>,
|
||||||
|
create_texture: impl FnOnce(usize) -> /*Option<Model<[u8; 4]>>*/F + Send,
|
||||||
|
(range, max_texture_size, boi): (Aabb<i32>, Vec2<u16>, &'a BlocksOfInterest),
|
||||||
|
) -> MeshGen<
|
||||||
|
TerrainVertex,
|
||||||
|
FluidVertex,
|
||||||
|
TerrainVertex,
|
||||||
|
(
|
||||||
|
Aabb<f32>,
|
||||||
|
/*ColLightInfo*/(Option<Model<[u8; 4]>>, Vec2<u16>),
|
||||||
|
Arc<dyn Fn(Vec3<i32>) -> f32 + Send + Sync>,
|
||||||
|
Arc<dyn Fn(Vec3<i32>) -> f32 + Send + Sync>,
|
||||||
|
AltIndices,
|
||||||
|
(f32, f32),
|
||||||
|
),
|
||||||
|
> {
|
||||||
|
/* span!(
|
||||||
|
_guard,
|
||||||
|
"generate_mesh",
|
||||||
|
"<&VolGrid2d as Meshable<_, _>>::generate_mesh"
|
||||||
|
); */
|
||||||
|
|
||||||
|
let (w, h, d) = range.size().into_tuple();
|
||||||
|
// z can range from -1..range.size().d + 1
|
||||||
|
let d = d + 2;
|
||||||
|
|
||||||
|
let PreparedLights { flat, row_kinds, z_start, z_end, light, glow } =
|
||||||
|
prepare_lights(vol, (range, boi));
|
||||||
|
|
||||||
|
let light = light.into_fn();
|
||||||
|
let glow = glow.into_fn();
|
||||||
|
|
||||||
let max_size = max_texture_size;
|
let max_size = max_texture_size;
|
||||||
assert!(z_end >= z_start);
|
assert!(z_end >= z_start);
|
||||||
@ -924,7 +1023,15 @@ pub async fn generate_mesh<'a, F: Future<Output=Option<Model<[u8; 4]>>> + 'a>(
|
|||||||
let mut greedy =
|
let mut greedy =
|
||||||
GreedyMesh::<guillotiere::SimpleAtlasAllocator>::new(max_size, greedy::terrain_config());
|
GreedyMesh::<guillotiere::SimpleAtlasAllocator>::new(max_size, greedy::terrain_config());
|
||||||
let greedy_size = Vec3::new(range.size().w - 2, range.size().h - 2, z_end - z_start + 1);
|
let greedy_size = Vec3::new(range.size().w - 2, range.size().h - 2, z_end - z_start + 1);
|
||||||
|
// NOTE: Terrain sizes are limited to 32 x 32 x 16384 (to fit in 24 bits: 5 + 5
|
||||||
|
// + 14). FIXME: Make this function fallible, since the terrain
|
||||||
|
// information might be dynamically generated which would make this hard
|
||||||
|
// to enforce.
|
||||||
|
assert!(greedy_size.x <= 32 && greedy_size.y <= 32 && greedy_size.z <= 16384);
|
||||||
|
// NOTE: Cast is safe by prior assertion on greedy_size; it fits into a u16,
|
||||||
|
// which always fits into a f32.
|
||||||
let max_bounds: Vec3<f32> = greedy_size.as_::<f32>();
|
let max_bounds: Vec3<f32> = greedy_size.as_::<f32>();
|
||||||
|
// NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16.
|
||||||
let mesh_delta = Vec3::new(0.0, 0.0, (z_start + range.min.z) as f32);
|
let mesh_delta = Vec3::new(0.0, 0.0, (z_start + range.min.z) as f32);
|
||||||
let mut opaque_deep = Vec::new();
|
let mut opaque_deep = Vec::new();
|
||||||
let mut opaque_shallow = Vec::new();
|
let mut opaque_shallow = Vec::new();
|
||||||
@ -938,13 +1045,6 @@ pub async fn generate_mesh<'a, F: Future<Output=Option<Model<[u8; 4]>>> + 'a>(
|
|||||||
let mut do_draw_greedy = #[inline(always)] |z_start: i32, z_end: i32| {
|
let mut do_draw_greedy = #[inline(always)] |z_start: i32, z_end: i32| {
|
||||||
// dbg!(range.min, z_start, z_end);
|
// dbg!(range.min, z_start, z_end);
|
||||||
let greedy_size = Vec3::new(range.size().w - 2, range.size().h - 2, z_end - z_start + 1);
|
let greedy_size = Vec3::new(range.size().w - 2, range.size().h - 2, z_end - z_start + 1);
|
||||||
// NOTE: Terrain sizes are limited to 32 x 32 x 16384 (to fit in 24 bits: 5 + 5
|
|
||||||
// + 14). FIXME: Make this function fallible, since the terrain
|
|
||||||
// information might be dynamically generated which would make this hard
|
|
||||||
// to enforce.
|
|
||||||
assert!(greedy_size.x <= 32 && greedy_size.y <= 32 && greedy_size.z <= 16384);
|
|
||||||
// NOTE: Cast is safe by prior assertion on greedy_size; it fits into a u16,
|
|
||||||
// which always fits into a f32.
|
|
||||||
// NOTE: Cast is safe by prior assertion on greedy_size; it fits into a u16,
|
// NOTE: Cast is safe by prior assertion on greedy_size; it fits into a u16,
|
||||||
// which always fits into a usize.
|
// which always fits into a usize.
|
||||||
let greedy_size = greedy_size.as_::<usize>();
|
let greedy_size = greedy_size.as_::<usize>();
|
||||||
|
@ -1128,6 +1128,8 @@ impl/*<V: RectRasterableVol>*/ Terrain<V> {
|
|||||||
for j in -1..2 {
|
for j in -1..2 {
|
||||||
let pos = pos + Vec2::new(i, j);
|
let pos = pos + Vec2::new(i, j);
|
||||||
|
|
||||||
|
let is_sender = (pos.x & 1) ^ (pos.y & 1);
|
||||||
|
|
||||||
let entry = self.mesh_todo.entry(pos);
|
let entry = self.mesh_todo.entry(pos);
|
||||||
let done_meshing = self.chunks.contains_key(&pos);
|
let done_meshing = self.chunks.contains_key(&pos);
|
||||||
let in_progress = done_meshing || matches!(entry, hash_map::Entry::Occupied(_));
|
let in_progress = done_meshing || matches!(entry, hash_map::Entry::Occupied(_));
|
||||||
|
@ -752,7 +752,7 @@ impl Settlement {
|
|||||||
BlockKind::Grass,
|
BlockKind::Grass,
|
||||||
BlockKind::Earth,
|
BlockKind::Earth,
|
||||||
BlockKind::Sand,
|
BlockKind::Sand,
|
||||||
BlockKind::Snow,
|
/* BlockKind::Snow, */
|
||||||
BlockKind::Rock,
|
BlockKind::Rock,
|
||||||
]
|
]
|
||||||
.contains(&block.kind())
|
.contains(&block.kind())
|
||||||
|
@ -1113,10 +1113,10 @@ impl Site {
|
|||||||
let mut underground = true;
|
let mut underground = true;
|
||||||
for z in -8..6 {
|
for z in -8..6 {
|
||||||
canvas.map(Vec3::new(wpos2d.x, wpos2d.y, alt + z), |b| {
|
canvas.map(Vec3::new(wpos2d.x, wpos2d.y, alt + z), |b| {
|
||||||
if b.kind() == BlockKind::Snow {
|
/*if b.kind() == BlockKind::Snow {
|
||||||
underground = false;
|
underground = false;
|
||||||
b.into_vacant()
|
b.into_vacant()
|
||||||
} else if b.is_filled() {
|
} else */if b.is_filled() {
|
||||||
if b.is_terrain() {
|
if b.is_terrain() {
|
||||||
Block::new(
|
Block::new(
|
||||||
BlockKind::Earth,
|
BlockKind::Earth,
|
||||||
@ -1196,10 +1196,10 @@ impl Site {
|
|||||||
} else {
|
} else {
|
||||||
SpriteKind::Empty
|
SpriteKind::Empty
|
||||||
};
|
};
|
||||||
if b.kind() == BlockKind::Snow {
|
/* if b.kind() == BlockKind::Snow {
|
||||||
underground = false;
|
underground = false;
|
||||||
b.into_vacant().with_sprite(sprite)
|
b.into_vacant().with_sprite(sprite)
|
||||||
} else if b.is_filled() {
|
} else */if b.is_filled() {
|
||||||
if b.is_terrain() {
|
if b.is_terrain() {
|
||||||
Block::new(
|
Block::new(
|
||||||
BlockKind::Earth,
|
BlockKind::Earth,
|
||||||
@ -1227,7 +1227,7 @@ impl Site {
|
|||||||
BlockKind::Grass,
|
BlockKind::Grass,
|
||||||
BlockKind::Earth,
|
BlockKind::Earth,
|
||||||
BlockKind::Sand,
|
BlockKind::Sand,
|
||||||
BlockKind::Snow,
|
/* BlockKind::Snow, */
|
||||||
BlockKind::Rock,
|
BlockKind::Rock,
|
||||||
]
|
]
|
||||||
.contains(&b.kind()) {
|
.contains(&b.kind()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user