A simple map viewer

mercator_tile_layer.rs 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. use ::std::ffi::CStr;
  2. use buffer::{Buffer, DrawMode};
  3. use context::Context;
  4. use coord::View;
  5. use map_view::MapView;
  6. use mercator_view::MercatorView;
  7. use program::Program;
  8. use tile_atlas::{TileAtlas, VisibleTilesProvider};
  9. use tile_cache::TileCache;
  10. use tile_source::TileSource;
  11. use vertex_attrib::VertexAttribParams;
  12. #[derive(Debug)]
  13. pub struct MercatorTileLayer {
  14. program: Program,
  15. buffer: Buffer,
  16. }
  17. impl MercatorTileLayer {
  18. pub fn new(
  19. cx: &mut Context,
  20. atlas: &TileAtlas,
  21. ) -> MercatorTileLayer
  22. {
  23. let buffer = Buffer::new(cx, &[], 0);
  24. check_gl_errors!(cx);
  25. cx.bind_buffer(buffer.id());
  26. let mut program = Program::new(
  27. cx,
  28. include_bytes!("../shader/map.vert"),
  29. include_bytes!("../shader/map.frag"),
  30. ).unwrap();
  31. check_gl_errors!(cx);
  32. program.add_texture(cx, atlas.texture(), CStr::from_bytes_with_nul(b"tex_map\0").unwrap());
  33. check_gl_errors!(cx);
  34. program.add_attribute(
  35. cx,
  36. CStr::from_bytes_with_nul(b"position\0").unwrap(),
  37. &VertexAttribParams::new(2, 8, 0)
  38. );
  39. program.add_attribute(
  40. cx,
  41. CStr::from_bytes_with_nul(b"tex_coord\0").unwrap(),
  42. &VertexAttribParams::new(2, 8, 2)
  43. );
  44. program.add_attribute(
  45. cx,
  46. CStr::from_bytes_with_nul(b"tex_minmax\0").unwrap(),
  47. &VertexAttribParams::new(4, 8, 4)
  48. );
  49. check_gl_errors!(cx);
  50. MercatorTileLayer {
  51. program,
  52. buffer,
  53. }
  54. }
  55. // Has to be called once before one or multiple calls to `draw`.
  56. pub fn prepare_draw(&mut self, cx: &mut Context, atlas: &TileAtlas) {
  57. self.program.enable_vertex_attribs(cx);
  58. self.program.set_vertex_attribs(cx, &self.buffer);
  59. cx.set_active_texture_unit(atlas.texture().unit());
  60. }
  61. pub fn draw(
  62. &mut self,
  63. cx: &mut Context,
  64. map_view: &MapView,
  65. source: &TileSource,
  66. cache: &mut TileCache,
  67. atlas: &mut TileAtlas,
  68. viewport_size: (u32, u32),
  69. snap_to_pixel: bool
  70. ) -> Result<usize, usize> {
  71. cache.set_view_location(View {
  72. source_id: source.id(),
  73. zoom: MercatorView::tile_zoom(map_view),
  74. center: map_view.center,
  75. });
  76. let visible_tiles = MercatorView::visible_tiles(map_view, snap_to_pixel);
  77. let mut remainder = visible_tiles.as_slice();
  78. let mut num_draws = 0;
  79. let mut max_tiles_to_use = cache.max_tiles();
  80. loop {
  81. let (textured_visible_tiles, remainder_opt, used_tiles) = {
  82. atlas.textured_visible_tiles(
  83. cx,
  84. remainder,
  85. max_tiles_to_use,
  86. source,
  87. cache,
  88. )
  89. };
  90. max_tiles_to_use -= used_tiles;
  91. let mut vertex_data: Vec<f32> = Vec::with_capacity(textured_visible_tiles.len() * (6 * 8));
  92. let scale_x = 2.0 / f64::from(viewport_size.0);
  93. let scale_y = -2.0 / f64::from(viewport_size.1);
  94. for tvt in &textured_visible_tiles {
  95. let minmax = [
  96. tvt.tex_minmax.x1 as f32,
  97. tvt.tex_minmax.y1 as f32,
  98. tvt.tex_minmax.x2 as f32,
  99. tvt.tex_minmax.y2 as f32,
  100. ];
  101. let p1 = [
  102. (tvt.screen_rect.x * scale_x - 1.0) as f32,
  103. (tvt.screen_rect.y * scale_y + 1.0) as f32,
  104. tvt.tex_rect.x1 as f32,
  105. tvt.tex_rect.y1 as f32,
  106. ];
  107. let p2 = [
  108. (tvt.screen_rect.x * scale_x - 1.0) as f32,
  109. ((tvt.screen_rect.y + tvt.screen_rect.height) * scale_y + 1.0) as f32,
  110. tvt.tex_rect.x1 as f32,
  111. tvt.tex_rect.y2 as f32,
  112. ];
  113. let p3 = [
  114. ((tvt.screen_rect.x + tvt.screen_rect.width) * scale_x - 1.0) as f32,
  115. ((tvt.screen_rect.y + tvt.screen_rect.height) * scale_y + 1.0) as f32,
  116. tvt.tex_rect.x2 as f32,
  117. tvt.tex_rect.y2 as f32,
  118. ];
  119. let p4 = [
  120. ((tvt.screen_rect.x + tvt.screen_rect.width) * scale_x - 1.0) as f32,
  121. (tvt.screen_rect.y * scale_y + 1.0) as f32,
  122. tvt.tex_rect.x2 as f32,
  123. tvt.tex_rect.y1 as f32,
  124. ];
  125. vertex_data.extend(&p1);
  126. vertex_data.extend(&minmax);
  127. vertex_data.extend(&p2);
  128. vertex_data.extend(&minmax);
  129. vertex_data.extend(&p3);
  130. vertex_data.extend(&minmax);
  131. vertex_data.extend(&p1);
  132. vertex_data.extend(&minmax);
  133. vertex_data.extend(&p3);
  134. vertex_data.extend(&minmax);
  135. vertex_data.extend(&p4);
  136. vertex_data.extend(&minmax);
  137. }
  138. self.buffer.set_data(cx, &vertex_data, vertex_data.len() / 4);
  139. self.buffer.draw(cx, &self.program, DrawMode::Triangles);
  140. num_draws += 1;
  141. debug!("draw #{}: tvt.len() = {}, remainder = {:?}, max_tiles = {}",
  142. num_draws,
  143. textured_visible_tiles.len(),
  144. remainder_opt.map(|r| r.len()),
  145. max_tiles_to_use);
  146. if max_tiles_to_use == 0 {
  147. warn!("tile cache is too small for this view.");
  148. return Err(num_draws);
  149. }
  150. match remainder_opt {
  151. None => return Ok(num_draws),
  152. Some(new_remainder) => {
  153. if new_remainder.len() >= remainder.len() {
  154. warn!("failed to draw all tiles. number of remaining tiles did not decrease.");
  155. return Err(num_draws);
  156. } else {
  157. remainder = new_remainder;
  158. }
  159. },
  160. }
  161. }
  162. }
  163. }