diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index 76436f13d6..585e76ce69 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -32,7 +32,7 @@ vec2 cloud_at(vec3 pos) { float density = max((value - CLOUD_THRESHOLD) - abs(pos.z - CLOUD_AVG_HEIGHT) / 200.0, 0.0) * CLOUD_DENSITY; const float SHADE_GRADIENT = 1.5 / (CLOUD_AVG_HEIGHT - CLOUD_HEIGHT_MIN); - float shade = ((pos.z - CLOUD_AVG_HEIGHT) / (CLOUD_HEIGHT_MAX - CLOUD_HEIGHT_MIN)) * 2.5 + 0.7; + float shade = ((pos.z - CLOUD_AVG_HEIGHT) / (CLOUD_HEIGHT_MAX - CLOUD_HEIGHT_MIN)) * 10.5 + 0.7; return vec2(shade, density / (1.0 + vsum(abs(pos - cam_pos.xyz)) / 5000)); } diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index c4edef3992..103e9b7d14 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -91,36 +91,6 @@ impl Civs { this.tick(&mut ctx, 1.0); } - // Temporary! - for track in this.tracks.iter() { - for locs in track.path.nodes().windows(3) { - let to_prev_idx = NEIGHBORS - .iter() - .enumerate() - .find(|(_, dir)| **dir == locs[0] - locs[1]) - .expect("Track locations must be neighbors") - .0; - let to_next_idx = NEIGHBORS - .iter() - .enumerate() - .find(|(_, dir)| **dir == locs[2] - locs[1]) - .expect("Track locations must be neighbors") - .0; - - let mut chunk = ctx.sim.get_mut(locs[1]).unwrap(); - chunk.path.neighbors |= (1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8)); - chunk.path.offset = Vec2::new( - ctx.rng.gen_range(-16.0, 16.0), - ctx.rng.gen_range(-16.0, 16.0), - ); - } - - for loc in track.path.iter() { - ctx.sim.get_mut(*loc).unwrap().place = - Some(this.civs.iter().next().unwrap().homeland); - } - } - // Flatten ground around sites for site in this.sites.iter() { if let SiteKind::Settlement = &site.kind { @@ -380,6 +350,30 @@ impl Civs { .filter(|(_, route_cost)| *route_cost < cost * 3.0) .is_none() { + // Write the track to the world as a path + for locs in path.nodes().windows(3) { + let to_prev_idx = NEIGHBORS + .iter() + .enumerate() + .find(|(_, dir)| **dir == locs[0] - locs[1]) + .expect("Track locations must be neighbors") + .0; + let to_next_idx = NEIGHBORS + .iter() + .enumerate() + .find(|(_, dir)| **dir == locs[2] - locs[1]) + .expect("Track locations must be neighbors") + .0; + + let mut chunk = ctx.sim.get_mut(locs[1]).unwrap(); + chunk.path.neighbors |= (1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8)); + chunk.path.offset = Vec2::new( + ctx.rng.gen_range(-16.0, 16.0), + ctx.rng.gen_range(-16.0, 16.0), + ); + } + + // Take note of the track let track = self.tracks.insert(Track { cost, path }); self.track_map .entry(site) @@ -491,14 +485,21 @@ fn find_path( /// (TODO: by whom?) fn walk_in_dir(sim: &WorldSim, a: Vec2, dir: Vec2) -> Option { if loc_suitable_for_walking(sim, a) && loc_suitable_for_walking(sim, a + dir) { - let a_alt = sim.get(a)?.alt; - let b_alt = sim.get(a + dir)?.alt; - let water_cost = if sim.get(a + dir)?.river.near_water() { - 25.0 + let a_chunk = sim.get(a)?; + let b_chunk = sim.get(a + dir)?; + + let hill_cost = ((b_chunk.alt - a_chunk.alt).abs() / 2.5).powf(2.0); + let water_cost = if b_chunk.river.near_water() { + 50.0 } else { 0.0 }; - Some(1.0 + ((b_alt - a_alt).abs() / 2.5).powf(2.0) + water_cost) + let wild_cost = if b_chunk.path.is_path() { + 0.0 // Traversing existing paths has no additional cost! + } else { + 2.0 + }; + Some(1.0 + hill_cost + water_cost + wild_cost) } else { None } diff --git a/world/src/layer/mod.rs b/world/src/layer/mod.rs index 5d0e7c06ae..348f59b9c1 100644 --- a/world/src/layer/mod.rs +++ b/world/src/layer/mod.rs @@ -43,21 +43,33 @@ pub fn apply_paths_to<'a>( // Try to use the column at the centre of the path for sampling to make them // flatter - let col_pos = offs + path_nearest.map(|e| e.floor() as i32) - wpos2d; - let col = get_column(col_pos) + let col_pos = (offs - wpos2d).map(|e| e as f32) + path_nearest; + let col00 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(0, 0)); + let col10 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(1, 0)); + let col01 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(0, 1)); + let col11 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(1, 1)); + let riverless_alt = match (col00, col10, col01, col11) { + (Some(col00), Some(col10), Some(col01), Some(col11)) => Lerp::lerp( + Lerp::lerp(col00.riverless_alt, col10.riverless_alt, path_nearest.x.fract()), + Lerp::lerp(col01.riverless_alt, col11.riverless_alt, path_nearest.x.fract()), + path_nearest.y.fract(), + ), + _ => col_sample.riverless_alt, + }; + let col = get_column(col_pos.map(|e| e.floor() as i32)) .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) + * (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; + let surface_z = (riverless_alt + bridge_offset).floor() as i32; for z in inset - depth..inset { vol.set( diff --git a/world/src/sim/map.rs b/world/src/sim/map.rs index 2a4d71d277..4dd96c3700 100644 --- a/world/src/sim/map.rs +++ b/world/src/sim/map.rs @@ -147,7 +147,7 @@ impl MapConfig { let pos = (focus_rect + Vec2::new(i as f64, j as f64) * scale).map(|e: f64| e as i32); - let (alt, basement, water_alt, humidity, temperature, downhill, river_kind, place) = + let (alt, basement, water_alt, humidity, temperature, downhill, river_kind, is_path) = sampler .get(pos) .map(|sample| { @@ -159,7 +159,7 @@ impl MapConfig { sample.temp, sample.downhill, sample.river.river_kind, - sample.place, + sample.path.is_path(), ) }) .unwrap_or(( @@ -170,7 +170,7 @@ impl MapConfig { 0.0, None, None, - None, + false, )); let humidity = humidity.min(1.0).max(0.0); let temperature = temperature.min(1.0).max(-1.0) * 0.5 + 0.5; @@ -297,8 +297,8 @@ impl MapConfig { ), }; - let rgba = if let Some(place) = place { - (((place.id() * 64) % 256) as u8, 0, 0, 0) + let rgba = if is_path { + (0x20, 0x19, 0x13, 255) } else { rgba }; diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 7e0e65052d..d651df51a6 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -1831,7 +1831,7 @@ impl WorldSim { end: (end_pos + ctrl_pos) / 2.0, }; let nearest_interval = bez - .binary_search_point_by_steps(wpos.map(|e| e as f32), 6, 0.01) + .binary_search_point_by_steps(wpos.map(|e| e as f32), 16, 0.001) .0 .clamped(0.0, 1.0); let pos = bez.evaluate(nearest_interval); diff --git a/world/src/sim/path.rs b/world/src/sim/path.rs index ea4f24df42..0ccdb910b8 100644 --- a/world/src/sim/path.rs +++ b/world/src/sim/path.rs @@ -7,6 +7,12 @@ pub struct PathData { pub neighbors: u8, // One bit for each neighbor } +impl PathData { + pub fn is_path(&self) -> bool { + self.neighbors != 0 + } +} + impl Default for PathData { fn default() -> Self { Self {