Lowered path priority

This commit is contained in:
Joshua Barretto 2020-06-30 12:28:25 +01:00
parent 41916d4594
commit 6a41f6aa88
8 changed files with 102 additions and 74 deletions

View File

@ -28,7 +28,7 @@ pub fn structure_gen<'a>(
|| st_sample.alt < st_sample.water_level
|| st_sample.spawn_rate < 0.5
|| st_sample.water_dist.map(|d| d < 8.0).unwrap_or(false)
|| st_sample.path.map(|(d, _)| d < 12.0).unwrap_or(false)
|| st_sample.path.map(|(d, _, _, _)| d < 12.0).unwrap_or(false)
{
return None;
}

View File

@ -1,7 +1,7 @@
use crate::{
all::ForestKind,
block::StructureMeta,
sim::{local_cells, uniform_idx_as_vec2, vec2_as_uniform_idx, RiverKind, SimChunk, WorldSim},
sim::{local_cells, uniform_idx_as_vec2, vec2_as_uniform_idx, RiverKind, SimChunk, WorldSim, Path},
util::Sampler,
Index, CONFIG,
};
@ -1157,7 +1157,7 @@ pub struct ColumnSample<'a> {
pub spawn_rate: f32,
pub stone_col: Rgb<u8>,
pub water_dist: Option<f32>,
pub path: Option<(f32, Vec2<f32>)>,
pub path: Option<(f32, Vec2<f32>, Path, Vec2<f32>)>,
pub chunk: &'a SimChunk,
}

View File

@ -37,7 +37,7 @@ pub fn apply_paths_to<'a>(
})
};
if let Some((path_dist, path_nearest)) = col_sample.path.filter(|(dist, _)| *dist < 5.0)
if let Some((path_dist, path_nearest, path, _)) = col_sample.path.filter(|(dist, _, path, _)| *dist < path.width)
{
let inset = 0;
@ -82,7 +82,7 @@ pub fn apply_paths_to<'a>(
},
);
}
let head_space = (8 - (path_dist * 0.25).powf(6.0).round() as i32).max(1);
let head_space = path.head_space(path_dist);
for z in inset..inset + head_space {
let pos = Vec3::new(offs.x, offs.y, surface_z + z);
if vol.get(pos).unwrap().kind() != BlockKind::Water {

View File

@ -175,14 +175,14 @@ impl World {
let mut rng = rand::thread_rng();
// Apply paths
layer::apply_paths_to(chunk_wpos2d, sample_get, &mut chunk);
// Apply site generation
sim_chunk.sites.iter().for_each(|site| {
self.index.sites[*site].apply_to(chunk_wpos2d, sample_get, &mut chunk)
});
// Apply paths
layer::apply_paths_to(chunk_wpos2d, sample_get, &mut chunk);
let gen_entity_pos = || {
let lpos2d = TerrainChunkSize::RECT_SIZE
.map(|sz| rand::thread_rng().gen::<u32>().rem_euclid(sz) as i32);

View File

@ -15,7 +15,7 @@ pub use self::{
},
location::Location,
map::{MapConfig, MapDebug},
path::PathData,
path::{Path, PathData},
util::{
cdf_irwin_hall, downhill, get_oceans, local_cells, map_edge_factor, neighbors,
uniform_idx_as_vec2, uniform_noise, uphill, vec2_as_uniform_idx, InverseCdf, ScaleBias,
@ -1699,7 +1699,9 @@ impl WorldSim {
Some(z0 + z1 + z2 + z3)
}
pub fn get_nearest_path(&self, wpos: Vec2<i32>) -> Option<(f32, Vec2<f32>)> {
/// Return the distance to the nearest path in blocks, along with the closest point on the path
/// and the tangent vector of that path.
pub fn get_nearest_path(&self, wpos: Vec2<i32>) -> Option<(f32, Vec2<f32>, Path, Vec2<f32>)> {
let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
e.div_euclid(sz as i32)
});
@ -1759,13 +1761,13 @@ impl WorldSim {
.clamped(0.0, 1.0);
let pos = bez.evaluate(nearest_interval);
let dist_sqrd = pos.distance_squared(wpos.map(|e| e as f32));
Some((dist_sqrd, pos))
Some((dist_sqrd, pos, chunk.path.path, move || bez.evaluate_derivative(nearest_interval).normalized()))
}),
)
})
.flatten()
.min_by_key(|(dist_sqrd, _)| (dist_sqrd * 1024.0) as i32)
.map(|(dist, pos)| (dist.sqrt(), pos))
.min_by_key(|(dist_sqrd, _, _, _)| (dist_sqrd * 1024.0) as i32)
.map(|(dist, pos, path, calc_tangent)| (dist.sqrt(), pos, path, calc_tangent()))
}
}

View File

@ -1,9 +1,15 @@
use vek::*;
#[derive(Copy, Clone, Debug)]
pub struct Path {
pub width: f32,
}
#[derive(Debug)]
pub struct PathData {
pub offset: Vec2<f32>, /* Offset from centre of chunk: must not be more than half chunk
* width in any direction */
pub path: Path,
pub neighbors: u8, // One bit for each neighbor
}
@ -15,7 +21,17 @@ impl Default for PathData {
fn default() -> Self {
Self {
offset: Vec2::zero(),
path: Path {
width: 5.0,
},
neighbors: 0,
}
}
}
impl Path {
/// Return the number of blocks of headspace required at the given path distance
pub fn head_space(&self, dist: f32) -> i32 {
(8 - (dist * 0.25).powf(6.0).round() as i32).max(1)
}
}

View File

@ -88,7 +88,7 @@ impl Castle {
if ctx
.sim
.and_then(|sim| sim.get_nearest_path(wpos + offset))
.map(|(dist, _)| dist > 24.0)
.map(|(dist, _, _, _)| dist > 24.0)
.unwrap_or(true)
{
break;
@ -202,6 +202,16 @@ impl Castle {
})
.min_by_key(|x| x.0)
.unwrap();
let border_pos = (wall_pos - rpos).map(|e| e.abs());
let wall_normal = (rpos - wall_pos).map(|e| e as f32);
let wall_rpos = if wall_ori == Ori::East {
rpos
} else {
rpos.yx()
};
let head_space = col_sample.path
.map(|(dist, _, path, _)| path.head_space(dist))
.unwrap_or(0);
// Apply the dungeon entrance
let wall_sample = if let Some(col) = get_column(offs + wall_pos - rpos) {
@ -218,27 +228,26 @@ impl Castle {
};
// Boundary
let border_pos = (wall_pos - rpos).map(|e| e.abs());
let wall_rpos = if wall_ori == Ori::East {
rpos
let wall_z = wpos.z - wall_alt;
let mut mask = if z < head_space {
BlockMask::nothing()
} else {
rpos.yx()
keep.draw(
Vec3::from(wall_rpos) + Vec3::unit_z() * wpos.z - wall_alt,
wall_dist,
Vec2::new(border_pos.reduce_max(), border_pos.reduce_min()),
rpos - wall_pos,
wall_z,
wall_ori,
4,
0,
&Attr {
height: 16,
is_tower: false,
rounded: true,
},
)
};
let mut mask = keep.draw(
Vec3::from(wall_rpos) + Vec3::unit_z() * wpos.z - wall_alt,
wall_dist,
Vec2::new(border_pos.reduce_max(), border_pos.reduce_min()),
rpos - wall_pos,
wpos.z - wall_alt,
wall_ori,
4,
0,
&Attr {
height: 16,
is_tower: false,
rounded: true,
},
);
for tower in &self.towers {
let tower_wpos = Vec3::new(
self.origin.x + tower.offset.x,

View File

@ -380,7 +380,7 @@ impl Settlement {
|| ctx
.sim
.and_then(|sim| sim.get_nearest_path(self.origin + house_pos))
.map(|(dist, _)| dist < 28.0)
.map(|(dist, _, _, _)| dist < 28.0)
.unwrap_or(false)
{
continue;
@ -590,45 +590,46 @@ impl Settlement {
}
// Paths
if let Some((WayKind::Path, dist, nearest)) = sample.way {
let inset = -1;
// if let Some((WayKind::Path, dist, nearest)) = sample.way {
// let inset = -1;
// Try to use the column at the centre of the path for sampling to make them
// flatter
let col = get_column(offs + (nearest.floor().map(|e| e as i32) - rpos))
.unwrap_or(col_sample);
let (bridge_offset, depth) = if let Some(water_dist) = col.water_dist {
(
((water_dist.max(0.0) * 0.2).min(f32::consts::PI).cos() + 1.0) * 5.0,
((1.0 - ((water_dist + 2.0) * 0.3).min(0.0).cos().abs())
* (col.riverless_alt + 5.0 - col.alt).max(0.0)
* 1.75
+ 3.0) as i32,
)
} else {
(0.0, 3)
};
let surface_z = (col.riverless_alt + bridge_offset).floor() as i32;
// // Try to use the column at the centre of the path for sampling to make them
// // flatter
// let col = get_column(offs + (nearest.floor().map(|e| e as i32) - rpos))
// .unwrap_or(col_sample);
// let (bridge_offset, depth) = if let Some(water_dist) = col.water_dist {
// (
// ((water_dist.max(0.0) * 0.2).min(f32::consts::PI).cos() + 1.0) * 5.0,
// ((1.0 - ((water_dist + 2.0) * 0.3).min(0.0).cos().abs())
// * (col.riverless_alt + 5.0 - col.alt).max(0.0)
// * 1.75
// + 3.0) as i32,
// )
// } else {
// (0.0, 3)
// };
// let surface_z = (col.riverless_alt + bridge_offset).floor() as i32;
for z in inset - depth..inset {
let _ = vol.set(
Vec3::new(offs.x, offs.y, surface_z + z),
if bridge_offset >= 2.0 && dist >= 3.0 || z < inset - 1 {
Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 80, 100), 8))
} else {
Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 50, 30), 8))
},
);
}
let head_space = (8 - (dist * 0.25).powf(6.0).round() as i32).max(1);
for z in inset..inset + head_space {
let pos = Vec3::new(offs.x, offs.y, surface_z + z);
if vol.get(pos).unwrap().kind() != BlockKind::Water {
let _ = vol.set(pos, Block::empty());
}
}
// Ground colour
} else {
// for z in inset - depth..inset {
// let _ = vol.set(
// Vec3::new(offs.x, offs.y, surface_z + z),
// if bridge_offset >= 2.0 && dist >= 3.0 || z < inset - 1 {
// Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 80, 100), 8))
// } else {
// Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 50, 30), 8))
// },
// );
// }
// let head_space = (8 - (dist * 0.25).powf(6.0).round() as i32).max(1);
// for z in inset..inset + head_space {
// let pos = Vec3::new(offs.x, offs.y, surface_z + z);
// if vol.get(pos).unwrap().kind() != BlockKind::Water {
// let _ = vol.set(pos, Block::empty());
// }
// }
// // Ground colour
// } else
{
let mut surface_block = None;
let roll =
@ -639,7 +640,7 @@ impl Settlement {
Some(Plot::Grass) => Some(Rgb::new(100, 200, 0)),
Some(Plot::Water) => Some(Rgb::new(100, 150, 250)),
Some(Plot::Town { district }) => {
if let Some((_, path_nearest)) = col_sample.path {
if let Some((_, path_nearest, _, _)) = col_sample.path {
let path_dir = (path_nearest - wpos2d.map(|e| e as f32))
.rotated_z(f32::consts::PI / 2.0)
.normalized();
@ -651,8 +652,8 @@ impl Settlement {
/ path_dir.dot(Vec2::unit_x()).abs()
<= 1.0
};
if (col_sample.path.map(|(dist, _)| dist > 6.0 && dist < 7.0).unwrap_or(false) && is_lamp) //roll(0, 50) == 0)
|| (roll(0, 2000) == 0 && col_sample.path.map(|(dist, _)| dist > 20.0).unwrap_or(true))
if (col_sample.path.map(|(dist, _, _, _)| dist > 6.0 && dist < 7.0).unwrap_or(false) && is_lamp) //roll(0, 50) == 0)
|| (roll(0, 2000) == 0 && col_sample.path.map(|(dist, _, _, _)| dist > 20.0).unwrap_or(true))
{
surface_block =
Some(Block::new(BlockKind::StreetLamp, Rgb::white()));