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.alt < st_sample.water_level
|| st_sample.spawn_rate < 0.5 || st_sample.spawn_rate < 0.5
|| st_sample.water_dist.map(|d| d < 8.0).unwrap_or(false) || 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; return None;
} }

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
all::ForestKind, all::ForestKind,
block::StructureMeta, 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, util::Sampler,
Index, CONFIG, Index, CONFIG,
}; };
@ -1157,7 +1157,7 @@ pub struct ColumnSample<'a> {
pub spawn_rate: f32, pub spawn_rate: f32,
pub stone_col: Rgb<u8>, pub stone_col: Rgb<u8>,
pub water_dist: Option<f32>, pub water_dist: Option<f32>,
pub path: Option<(f32, Vec2<f32>)>, pub path: Option<(f32, Vec2<f32>, Path, Vec2<f32>)>,
pub chunk: &'a SimChunk, 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; 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 { for z in inset..inset + head_space {
let pos = Vec3::new(offs.x, offs.y, surface_z + z); let pos = Vec3::new(offs.x, offs.y, surface_z + z);
if vol.get(pos).unwrap().kind() != BlockKind::Water { if vol.get(pos).unwrap().kind() != BlockKind::Water {

View File

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

View File

@ -15,7 +15,7 @@ pub use self::{
}, },
location::Location, location::Location,
map::{MapConfig, MapDebug}, map::{MapConfig, MapDebug},
path::PathData, path::{Path, PathData},
util::{ util::{
cdf_irwin_hall, downhill, get_oceans, local_cells, map_edge_factor, neighbors, 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, uniform_idx_as_vec2, uniform_noise, uphill, vec2_as_uniform_idx, InverseCdf, ScaleBias,
@ -1699,7 +1699,9 @@ impl WorldSim {
Some(z0 + z1 + z2 + z3) 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| { let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
e.div_euclid(sz as i32) e.div_euclid(sz as i32)
}); });
@ -1759,13 +1761,13 @@ impl WorldSim {
.clamped(0.0, 1.0); .clamped(0.0, 1.0);
let pos = bez.evaluate(nearest_interval); let pos = bez.evaluate(nearest_interval);
let dist_sqrd = pos.distance_squared(wpos.map(|e| e as f32)); 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() .flatten()
.min_by_key(|(dist_sqrd, _)| (dist_sqrd * 1024.0) as i32) .min_by_key(|(dist_sqrd, _, _, _)| (dist_sqrd * 1024.0) as i32)
.map(|(dist, pos)| (dist.sqrt(), pos)) .map(|(dist, pos, path, calc_tangent)| (dist.sqrt(), pos, path, calc_tangent()))
} }
} }

View File

@ -1,9 +1,15 @@
use vek::*; use vek::*;
#[derive(Copy, Clone, Debug)]
pub struct Path {
pub width: f32,
}
#[derive(Debug)] #[derive(Debug)]
pub struct PathData { pub struct PathData {
pub offset: Vec2<f32>, /* Offset from centre of chunk: must not be more than half chunk pub offset: Vec2<f32>, /* Offset from centre of chunk: must not be more than half chunk
* width in any direction */ * width in any direction */
pub path: Path,
pub neighbors: u8, // One bit for each neighbor pub neighbors: u8, // One bit for each neighbor
} }
@ -15,7 +21,17 @@ impl Default for PathData {
fn default() -> Self { fn default() -> Self {
Self { Self {
offset: Vec2::zero(), offset: Vec2::zero(),
path: Path {
width: 5.0,
},
neighbors: 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 if ctx
.sim .sim
.and_then(|sim| sim.get_nearest_path(wpos + offset)) .and_then(|sim| sim.get_nearest_path(wpos + offset))
.map(|(dist, _)| dist > 24.0) .map(|(dist, _, _, _)| dist > 24.0)
.unwrap_or(true) .unwrap_or(true)
{ {
break; break;
@ -202,6 +202,16 @@ impl Castle {
}) })
.min_by_key(|x| x.0) .min_by_key(|x| x.0)
.unwrap(); .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 // Apply the dungeon entrance
let wall_sample = if let Some(col) = get_column(offs + wall_pos - rpos) { let wall_sample = if let Some(col) = get_column(offs + wall_pos - rpos) {
@ -218,18 +228,16 @@ impl Castle {
}; };
// Boundary // Boundary
let border_pos = (wall_pos - rpos).map(|e| e.abs()); let wall_z = wpos.z - wall_alt;
let wall_rpos = if wall_ori == Ori::East { let mut mask = if z < head_space {
rpos BlockMask::nothing()
} else { } else {
rpos.yx() keep.draw(
};
let mut mask = keep.draw(
Vec3::from(wall_rpos) + Vec3::unit_z() * wpos.z - wall_alt, Vec3::from(wall_rpos) + Vec3::unit_z() * wpos.z - wall_alt,
wall_dist, wall_dist,
Vec2::new(border_pos.reduce_max(), border_pos.reduce_min()), Vec2::new(border_pos.reduce_max(), border_pos.reduce_min()),
rpos - wall_pos, rpos - wall_pos,
wpos.z - wall_alt, wall_z,
wall_ori, wall_ori,
4, 4,
0, 0,
@ -238,7 +246,8 @@ impl Castle {
is_tower: false, is_tower: false,
rounded: true, rounded: true,
}, },
); )
};
for tower in &self.towers { for tower in &self.towers {
let tower_wpos = Vec3::new( let tower_wpos = Vec3::new(
self.origin.x + tower.offset.x, self.origin.x + tower.offset.x,

View File

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