Skip to content

Commit

Permalink
heightfinder on interfaced points + fix visual artefacts
Browse files Browse the repository at this point in the history
  • Loading branch information
Uriopass committed Jan 3, 2024
1 parent d9cddc5 commit 0e17c41
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 61 deletions.
33 changes: 15 additions & 18 deletions native_app/src/gui/roadbuild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ pub fn roadbuild(sim: &Simulation, uiworld: &mut UiWorld) {
if let proj @ MapProject { kind: Inter(_), .. } =
map.project(to.pos, 0.0, ProjectFilter::ALL)
{
state.build_state = Start(proj);
if matches!(tool, Tool::RoadbuildCurved) {
state.build_state = StartInterp(proj);
} else {
state.build_state = Start(proj);
}
}
}
}
Expand Down Expand Up @@ -222,23 +226,17 @@ pub fn roadbuild(sim: &Simulation, uiworld: &mut UiWorld) {
None => RoadSegmentKind::Straight,
};

points = match simulation::map::Road::generate_points(
let (p, err) = simulation::map::Road::generate_points(
selected_proj.pos,
cur_proj.pos,
connection_segment,
is_rail,
&map.environment,
) {
Ok(p) => Some(p),
Err((p, _err)) => {
is_valid = false;
if let Some(p) = p {
Some(p)
} else {
None
}
}
};
);
points = Some(p);
if err.is_some() {
is_valid = false;
}
}

state.update_drawing(map, immdraw, cur_proj, patwidth, is_valid, points);
Expand Down Expand Up @@ -315,7 +313,9 @@ fn check_angle(map: &Map, from: MapProject, to: Vec2, is_rail: bool) -> bool {
true
}
Road(r) => {
let r = &map.roads()[r]; // fixme don't crash
let Some(r) = map.roads().get(r) else {
return false;
};
let (proj, _, rdir1) = r.points().project_segment_dir(from.pos);
let rdir2 = -rdir1;
let dir = (to - proj.xy()).normalize();
Expand All @@ -331,10 +331,7 @@ fn check_angle(map: &Map, from: MapProject, to: Vec2, is_rail: bool) -> bool {
}

fn compatible(map: &Map, x: MapProject, y: MapProject) -> bool {
// enforce at most 18 deg angle
if x.pos.distance(y.pos) < 10.0
|| (x.pos.z - y.pos.z).abs() > 0.2 * x.pos.xy().distance(y.pos.xy())
{
if x.pos.distance(y.pos) < 10.0 {
return false;
}
match (x.kind, y.kind) {
Expand Down
23 changes: 14 additions & 9 deletions native_app/src/rendering/map_rendering/map_mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use geom::{minmax, vec2, vec3, Color, LinearColor, PolyLine3, Polygon, Radians,
use simulation::map::{
Building, BuildingKind, CanonicalPosition, Environment, Intersection, LaneKind, Lanes, LotKind,
Map, MapSubscriber, ProjectFilter, ProjectKind, PylonPosition, Road, Roads, SubscriberChunkID,
Turn, TurnKind, UpdateType, CROSSWALK_WIDTH,
Turn, TurnKind, UpdateType, CROSSWALK_WIDTH, ROAD_Z_OFFSET,
};
use simulation::souls::goods_company::GoodsCompanyRegistry;
use simulation::Simulation;
Expand Down Expand Up @@ -665,12 +665,14 @@ impl MapBuilders {
for inter in chunk_inters {
let inter = &inters[inter];

let interpos = inter.pos.up(ROAD_Z_OFFSET);

if inter.roads.is_empty() {
self.tess_map.set_color(line_col);
self.tess_map.draw_circle(inter.pos, 5.5);
self.tess_map.draw_circle(interpos, 5.5);

self.tess_map.set_color(mid_col);
self.tess_map.draw_circle(inter.pos, 5.0);
self.tess_map.draw_circle(interpos, 5.0);
continue;
}

Expand Down Expand Up @@ -756,7 +758,7 @@ fn add_polyon(
let color: [f32; 4] = color.into();

let up = pos.up(-0.2);
let down = pos.xy().z(terrain_height);
let down = pos.xy().z(terrain_height - 20.0);
let dirp = dir.perp_up();
let d2 = dir.xy().z0();
let d2p = d2.perp_up();
Expand Down Expand Up @@ -833,8 +835,10 @@ fn inter_pylon(
inter: &Intersection,
roads: &Roads,
) {
let interpos = inter.pos.up(ROAD_Z_OFFSET);

let h = unwrap_ret!(env.height(inter.pos.xy()));
if (h - inter.pos.z).abs() <= 2.0 {
if (h - interpos.z).abs() <= 2.0 {
return;
}

Expand All @@ -849,7 +853,7 @@ fn inter_pylon(
if !inter.roads.is_empty() {
avgp /= inter.roads.len() as f32;
} else {
avgp = inter.pos;
avgp = interpos;
}

add_polyon(
Expand All @@ -869,6 +873,7 @@ fn intersection_mesh(
inter: &Intersection,
roads: &Roads,
) {
let interpos = inter.pos.up(ROAD_Z_OFFSET);
let id = inter.id;

let getw = |road: &Road| {
Expand Down Expand Up @@ -921,7 +926,7 @@ fn intersection_mesh(

if inter.is_roundabout() {
if let Some(rp) = inter.turn_policy.roundabout {
let center = inter.pos.xy();
let center = interpos.xy();

let ang = (left - center)
.normalize()
Expand All @@ -938,7 +943,7 @@ fn intersection_mesh(
));

tess.set_color(center_col);
tess.draw_circle(center.z(inter.pos.z + 0.01), rp.radius * 0.5);
tess.draw_circle(center.z(interpos.z + 0.01), rp.radius * 0.5);

continue;
}
Expand All @@ -956,7 +961,7 @@ fn intersection_mesh(
tess.meshbuilder
.extend_with(None, move |vertices, add_idx| {
vertices.extend(polygon.iter().map(|pos| MeshVertex {
position: pos.z(inter.pos.z - 0.001).into(),
position: pos.z(interpos.z - 0.001).into(),
normal: Vec3::Z,
uv: [0.0; 2],
color: col,
Expand Down
2 changes: 1 addition & 1 deletion native_app/src/rendering/map_rendering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl MapRenderer {
0.0
};
let w = r.width * 0.5 - offset;
for (point, dir) in r.points().equipoints_dir(45.0, true) {
for (point, dir) in r.interfaced_points().equipoints_dir(45.0, true) {
draw.mesh("streetlamp.glb", point - dir.perp_up() * w, dir.perp_up());
}
}
Expand Down
3 changes: 2 additions & 1 deletion simulation/src/map/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ impl Map {
self.lots.retain(|_, lot| {
let to_remove = lot.parent == road_id;
if to_remove {
self.subscribers.dispatch(UpdateType::Road, lot);
smap.remove(lot.id);
}
!to_remove
Expand Down Expand Up @@ -407,7 +408,7 @@ impl Map {
other_end.update_interface_radius(&mut self.roads);

#[allow(clippy::indexing_slicing)] // borrowed before
self.roads[x].update_lanes(&mut self.lanes, &mut self.parking);
self.roads[x].update_lanes(&mut self.lanes, &mut self.parking, &self.environment);
}

#[allow(clippy::indexing_slicing)] // borrowed before
Expand Down
68 changes: 36 additions & 32 deletions simulation/src/map/objects/road.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use slotmapd::new_key_type;

use geom::PolyLine;
use geom::{lerp, BoldLine, Degrees, PolyLine3, Spline, Spline1};
use geom::{BoldLine, Degrees, PolyLine3, Spline, Spline1};
use geom::{Vec2, Vec3};

use crate::map::{
Expand Down Expand Up @@ -81,17 +81,13 @@ impl Road {
spatial: &mut SpatialMap,
) -> RoadID {
let width = lane_pattern.width();
let points = match Self::generate_points(
let (points, _err) = Self::generate_points(
src.pos,
dst.pos,
segment,
lane_pattern.lanes().any(|(a, _, _)| a.is_rail()),
env,
) {
Ok(v) => v,
Err((Some(v), _)) => v,
_ => PolyLine3::new(vec![src.pos, dst.pos]),
};
);

let id = roads.insert_with_key(|id| Self {
id,
Expand Down Expand Up @@ -121,7 +117,7 @@ impl Road {
dist_from_bottom += lane_k.width();
}

road.update_lanes(lanes, parking);
road.update_lanes(lanes, parking, env);

spatial.insert(id, road.boldline());
road.id
Expand Down Expand Up @@ -197,8 +193,13 @@ impl Road {
}
}

pub fn update_lanes(&mut self, lanes: &mut Lanes, parking: &mut ParkingSpots) {
self.update_interfaced_points();
pub fn update_lanes(
&mut self,
lanes: &mut Lanes,
parking: &mut ParkingSpots,
env: &Environment,
) {
self.update_interfaced_points(env);
for (id, _) in self.lanes_iter() {
let l = unwrap_contlog!(lanes.get_mut(id), "lane in road does not exist anymore");
l.gen_pos(self);
Expand Down Expand Up @@ -276,27 +277,24 @@ impl Road {
&self.interfaced_points
}

fn update_interfaced_points(&mut self) {
fn update_interfaced_points(&mut self, env: &Environment) {
let points = &self.points;
self.interfaced_points =
points.cut(self.interface_from(self.src), self.interface_from(self.dst));

let cpoints = &mut self.interfaced_points;
let z_beg = self.points.first().z;
let z_end = self.points.last().z;

let start = cpoints.first().clone();
let end = cpoints.last().clone();

for v in cpoints.iter_mut_unchecked() {
let start_coeff = v.distance(start) / 15.0;
v.z = lerp(z_beg, v.z, start_coeff.clamp(0.0, 1.0));

let end_coeff = v.distance(end) / 15.0;
v.z = lerp(z_end, v.z, end_coeff.clamp(0.0, 1.0));
}
let z_beg = self.points.first().z - ROAD_Z_OFFSET;
let z_end = self.points.last().z - ROAD_Z_OFFSET;

let (p, _) = Self::heightfinder(
&PolyLine::new(cpoints.iter().map(|v| v.xy()).collect::<Vec<_>>()),
z_beg,
z_end,
MAX_SLOPE,
env,
);

cpoints.recalculate_length();
self.interfaced_points = p;
}

// Run an algorithm to find the height of the road at each point
Expand All @@ -316,22 +314,24 @@ impl Road {
end_height: f32,
maxslope: f32,
env: &Environment,
) -> Result<PolyLine3, (Option<PolyLine3>, PointGenerateError)> {
) -> (PolyLine3, Option<PointGenerateError>) {
// first calculate the contour

let mut contour = Vec::with_capacity(p.length() as usize + 2);
let mut points = Vec::with_capacity(contour.len());

let mut height_error = false;
for pos in std::iter::once(p.first())
.chain(
p.points_dirs_along((1..p.length() as u32).map(|v| v as f32))
.map(|v| v.0),
)
.chain(std::iter::once(p.last()))
{
let h = env
.height(pos)
.ok_or((None, PointGenerateError::OutsideOfMap))?;
let h = env.height(pos).unwrap_or_else(|| {
height_error = true;
0.0
});
contour.push(h);
points.push(pos.z(h));
}
Expand Down Expand Up @@ -445,11 +445,15 @@ impl Road {
let mut points = PolyLine3::new(points);
points.simplify(Degrees(1.0).into(), 1.0, 100.0);

if height_error {
return (points, Some(PointGenerateError::OutsideOfMap));
}

if slope_was_too_steep {
return Err((Some(points), PointGenerateError::TooSteep));
return (points, Some(PointGenerateError::TooSteep));
}

Ok(points)
(points, None)
}

pub fn generate_points(
Expand All @@ -458,7 +462,7 @@ impl Road {
segment: RoadSegmentKind,
precise: bool,
env: &Environment,
) -> Result<PolyLine3, (Option<PolyLine3>, PointGenerateError)> {
) -> (PolyLine3, Option<PointGenerateError>) {
let spline = match segment {
RoadSegmentKind::Straight => {
let p = PolyLine::new(vec![from.xy(), to.xy()]);
Expand Down

0 comments on commit 0e17c41

Please sign in to comment.