mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 20:29:04 +03:00
using prerender for lanes... a good start.
This commit is contained in:
parent
623e578665
commit
25bc02fb32
@ -67,6 +67,8 @@
|
||||
|
||||
- speed
|
||||
- change ezgui API to allow uploading geometry once
|
||||
- polyline -> arrow polygon. then collapse all lane markings into one Drawable.
|
||||
|
||||
- what about color then? get fancy and plumb an override color uniform?
|
||||
- stop storing raw geometry when appropriate
|
||||
- should the API for batching be easier? make a bunch of mutable calls to GfxCtx-like thing, then flush it?
|
||||
|
@ -93,7 +93,9 @@ fn change_lane_type(id: LaneID, new_type: LaneType, ctx: &mut PluginCtx) {
|
||||
// TODO Pretty sure control layer needs to recalculate based on the new turns
|
||||
let old_type = ctx.primary.map.get_l(id).lane_type;
|
||||
ctx.primary.map.edit_lane_type(id, new_type);
|
||||
ctx.primary.draw_map.edit_lane_type(id, &ctx.primary.map);
|
||||
ctx.primary
|
||||
.draw_map
|
||||
.edit_lane_type(id, &ctx.primary.map, &ctx.cs, &ctx.prerender);
|
||||
ctx.primary
|
||||
.sim
|
||||
.edit_lane_type(id, old_type, &ctx.primary.map);
|
||||
|
@ -5,13 +5,16 @@ use crate::render::{
|
||||
PARCEL_BOUNDARY_THICKNESS,
|
||||
};
|
||||
use dimensioned::si;
|
||||
use ezgui::{Color, GfxCtx};
|
||||
use ezgui::{Color, GfxCtx, Prerender};
|
||||
use geom::{Bounds, Circle, Line, Polygon, Pt2D};
|
||||
use map_model::{
|
||||
IntersectionType, Lane, LaneID, LaneType, Map, Road, Turn, LANE_THICKNESS, PARKING_SPOT_LENGTH,
|
||||
};
|
||||
|
||||
// Just a function to draw something later.
|
||||
// TODO Do we need to pass ColorScheme?
|
||||
// TODO This can maybe just be Drawables
|
||||
// TODO Or even just accumulate a bunch of (Color, Poly) and then make one Drawable.
|
||||
type Marking = Box<Fn(&mut GfxCtx, &ColorScheme)>;
|
||||
|
||||
pub struct DrawLane {
|
||||
@ -22,32 +25,30 @@ pub struct DrawLane {
|
||||
}
|
||||
|
||||
impl DrawLane {
|
||||
pub fn new(lane: &Lane, map: &Map) -> DrawLane {
|
||||
pub fn new(lane: &Lane, map: &Map, cs: &ColorScheme, prerender: &Prerender) -> DrawLane {
|
||||
let road = map.get_r(lane.parent);
|
||||
let polygon = lane.lane_center_pts.make_polygons(LANE_THICKNESS);
|
||||
|
||||
let mut markings: Vec<Marking> = Vec::new();
|
||||
if road.is_canonical_lane(lane.id) {
|
||||
let lines = road.center_pts.lines();
|
||||
markings.push(Box::new(move |g, cs| {
|
||||
for line in &lines {
|
||||
g.draw_line(
|
||||
cs.get_def("road center line", Color::YELLOW),
|
||||
BIG_ARROW_THICKNESS,
|
||||
line,
|
||||
);
|
||||
}
|
||||
let center_poly = road.center_pts.make_polygons(BIG_ARROW_THICKNESS);
|
||||
let draw_center = prerender.upload(vec![(
|
||||
cs.get_def("road center line", Color::YELLOW),
|
||||
¢er_poly,
|
||||
)]);
|
||||
markings.push(Box::new(move |g, _| {
|
||||
g.redraw(&draw_center);
|
||||
}));
|
||||
}
|
||||
match lane.lane_type {
|
||||
LaneType::Sidewalk => {
|
||||
markings.push(calculate_sidewalk_lines(lane));
|
||||
markings.push(calculate_sidewalk_lines(lane, cs, prerender));
|
||||
}
|
||||
LaneType::Parking => {
|
||||
markings.push(calculate_parking_lines(lane));
|
||||
markings.push(calculate_parking_lines(lane, cs, prerender));
|
||||
}
|
||||
LaneType::Driving | LaneType::Bus => {
|
||||
if let Some(m) = calculate_driving_lines(lane, road) {
|
||||
if let Some(m) = calculate_driving_lines(lane, road, cs, prerender) {
|
||||
markings.push(m);
|
||||
}
|
||||
for m in calculate_turn_markings(map, lane) {
|
||||
@ -138,29 +139,34 @@ fn perp_line(l: Line, length: f64) -> Line {
|
||||
Line::new(pt1, pt2)
|
||||
}
|
||||
|
||||
fn calculate_sidewalk_lines(lane: &Lane) -> Marking {
|
||||
fn calculate_sidewalk_lines(lane: &Lane, cs: &ColorScheme, prerender: &Prerender) -> Marking {
|
||||
let tile_every = LANE_THICKNESS * si::M;
|
||||
|
||||
let length = lane.length();
|
||||
|
||||
let mut draw = Vec::new();
|
||||
let mut polygons = Vec::new();
|
||||
// Start away from the intersections
|
||||
let mut dist_along = tile_every;
|
||||
while dist_along < length - tile_every {
|
||||
let (pt, angle) = lane.dist_along(dist_along);
|
||||
// Reuse perp_line. Project away an arbitrary amount
|
||||
let pt2 = pt.project_away(1.0, angle);
|
||||
draw.push(perp_line(Line::new(pt, pt2), LANE_THICKNESS).make_polygons(0.25));
|
||||
polygons.push(perp_line(Line::new(pt, pt2), LANE_THICKNESS).make_polygons(0.25));
|
||||
dist_along += tile_every;
|
||||
}
|
||||
|
||||
Box::new(move |g, cs| {
|
||||
let color = cs.get_def("sidewalk lines", Color::grey(0.7));
|
||||
g.draw_polygon_batch(draw.iter().map(|poly| (color, poly)).collect());
|
||||
let draw_lines = prerender.upload(
|
||||
polygons
|
||||
.iter()
|
||||
.map(|poly| (cs.get_def("sidewalk lines", Color::grey(0.7)), poly))
|
||||
.collect(),
|
||||
);
|
||||
Box::new(move |g, _| {
|
||||
g.redraw(&draw_lines);
|
||||
})
|
||||
}
|
||||
|
||||
fn calculate_parking_lines(lane: &Lane) -> Marking {
|
||||
fn calculate_parking_lines(lane: &Lane, cs: &ColorScheme, prerender: &Prerender) -> Marking {
|
||||
// meters, but the dims get annoying below to remove
|
||||
// TODO make Pt2D natively understand meters, projecting away by an angle
|
||||
let leg_length = 1.0;
|
||||
@ -186,13 +192,22 @@ fn calculate_parking_lines(lane: &Lane) -> Marking {
|
||||
}
|
||||
}
|
||||
|
||||
Box::new(move |g, cs| {
|
||||
let color = cs.get_def("parking lines", Color::WHITE);
|
||||
g.draw_polygon_batch(draw.iter().map(|poly| (color, poly)).collect());
|
||||
let draw_spots = prerender.upload(
|
||||
draw.iter()
|
||||
.map(|poly| (cs.get_def("parking lines", Color::WHITE), poly))
|
||||
.collect(),
|
||||
);
|
||||
Box::new(move |g, _| {
|
||||
g.redraw(&draw_spots);
|
||||
})
|
||||
}
|
||||
|
||||
fn calculate_driving_lines(lane: &Lane, parent: &Road) -> Option<Marking> {
|
||||
fn calculate_driving_lines(
|
||||
lane: &Lane,
|
||||
parent: &Road,
|
||||
cs: &ColorScheme,
|
||||
prerender: &Prerender,
|
||||
) -> Option<Marking> {
|
||||
// The leftmost lanes don't have dashed white lines.
|
||||
if parent.dir_and_offset(lane.id).1 == 0 {
|
||||
return None;
|
||||
@ -211,9 +226,14 @@ fn calculate_driving_lines(lane: &Lane, parent: &Road) -> Option<Marking> {
|
||||
.0
|
||||
.dashed_polygons(0.25, dash_len, dash_separation);
|
||||
|
||||
Some(Box::new(move |g, cs| {
|
||||
let color = cs.get_def("dashed lane line", Color::WHITE);
|
||||
g.draw_polygon_batch(polygons.iter().map(|poly| (color, poly)).collect());
|
||||
let draw_dashes = prerender.upload(
|
||||
polygons
|
||||
.iter()
|
||||
.map(|poly| (cs.get_def("dashed lane line", Color::WHITE), poly))
|
||||
.collect(),
|
||||
);
|
||||
Some(Box::new(move |g, _| {
|
||||
g.redraw(&draw_dashes);
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ impl DrawMap {
|
||||
timer.start_iter("make DrawLanes", map.all_lanes().len());
|
||||
for l in map.all_lanes() {
|
||||
timer.next();
|
||||
lanes.push(DrawLane::new(l, map));
|
||||
lanes.push(DrawLane::new(l, map, cs, prerender));
|
||||
}
|
||||
|
||||
let mut turn_to_lane_offset: HashMap<TurnID, usize> = HashMap::new();
|
||||
@ -175,9 +175,15 @@ impl DrawMap {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edit_lane_type(&mut self, id: LaneID, map: &Map) {
|
||||
pub fn edit_lane_type(
|
||||
&mut self,
|
||||
id: LaneID,
|
||||
map: &Map,
|
||||
cs: &ColorScheme,
|
||||
prerender: &Prerender,
|
||||
) {
|
||||
// No need to edit the quadtree; the bbox shouldn't depend on lane type.
|
||||
self.lanes[id.0] = DrawLane::new(map.get_l(id), map);
|
||||
self.lanes[id.0] = DrawLane::new(map.get_l(id), map, cs, prerender);
|
||||
}
|
||||
|
||||
pub fn edit_remove_turn(&mut self, id: TurnID) {
|
||||
|
@ -168,10 +168,10 @@ impl<'a> GfxCtx<'a> {
|
||||
}
|
||||
.upload(list);
|
||||
self.num_new_uploads += 1;
|
||||
self.draw(&obj);
|
||||
self.redraw(&obj);
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, obj: &Drawable) {
|
||||
pub fn redraw(&mut self, obj: &Drawable) {
|
||||
self.target
|
||||
.draw(
|
||||
&obj.vertex_buffer,
|
||||
@ -196,6 +196,8 @@ pub struct Drawable {
|
||||
}
|
||||
|
||||
impl<'a> Prerender<'a> {
|
||||
// TODO Taking &Polygon is annoying for the callers
|
||||
// TODO One color, many polygons could also be helpful
|
||||
pub fn upload(&self, list: Vec<(Color, &Polygon)>) -> Drawable {
|
||||
let mut vertices: Vec<Vertex> = Vec::new();
|
||||
let mut indices: Vec<u32> = Vec::new();
|
||||
|
Loading…
Reference in New Issue
Block a user