A simple map viewer

marker_layer.rs 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. use ::std::ffi::CStr;
  2. use buffer::{Buffer, DrawMode};
  3. use cgmath::{Matrix3, Point2, Transform, vec2, vec3};
  4. use context::Context;
  5. use coord::{MapCoord, ScreenRect};
  6. use image;
  7. use map_view::MapView;
  8. use program::Program;
  9. use texture::Texture;
  10. use vertex_attrib::VertexAttribParams;
  11. #[derive(Debug)]
  12. pub struct MarkerLayer {
  13. buffer: Buffer,
  14. program: Program,
  15. texture: Texture,
  16. positions: Vec<MapCoord>,
  17. }
  18. impl MarkerLayer {
  19. pub fn new(cx: &mut Context) -> MarkerLayer {
  20. let buffer = Buffer::new(cx, &[], 0);
  21. cx.bind_buffer(buffer.id());
  22. check_gl_errors!(cx);
  23. let mut program = Program::new(
  24. cx,
  25. include_bytes!("../shader/marker.vert"),
  26. include_bytes!("../shader/marker.frag"),
  27. ).unwrap();
  28. check_gl_errors!(cx);
  29. let texture = {
  30. let img = image::load_from_memory(
  31. include_bytes!("../img/marker.png"),
  32. ).unwrap();
  33. Texture::new(cx, &img).unwrap()
  34. };
  35. program.add_texture(cx, &texture, CStr::from_bytes_with_nul(b"tex\0").unwrap());
  36. program.add_attribute(
  37. cx,
  38. CStr::from_bytes_with_nul(b"position\0").unwrap(),
  39. &VertexAttribParams::new(2, 4, 0)
  40. );
  41. program.add_attribute(
  42. cx,
  43. CStr::from_bytes_with_nul(b"tex_coord\0").unwrap(),
  44. &VertexAttribParams::new(2, 4, 2)
  45. );
  46. MarkerLayer {
  47. buffer,
  48. program,
  49. texture,
  50. positions: vec![],
  51. }
  52. }
  53. pub fn is_empty(&self) -> bool {
  54. self.positions.is_empty()
  55. }
  56. pub fn add_marker(&mut self, map_coord: MapCoord) {
  57. self.positions.push(map_coord);
  58. }
  59. // Has to be called once before one or multiple calls to `draw`.
  60. pub fn prepare_draw(&mut self, cx: &mut Context) {
  61. cx.set_active_texture_unit(self.texture.unit());
  62. self.program.enable_vertex_attribs(cx);
  63. self.program.set_vertex_attribs(cx, &self.buffer);
  64. }
  65. pub fn draw(
  66. &mut self,
  67. cx: &mut Context,
  68. map_view: &MapView,
  69. viewport_size: (u32, u32),
  70. snap_to_pixel: bool
  71. ) {
  72. let mut vertex_data: Vec<f32> = vec![];
  73. let marker_size = vec2::<f64>(40.0, 50.0);
  74. let marker_offset = vec2::<f64>(-20.0, -50.0);
  75. let scale_x = 2.0 / viewport_size.0 as f32;
  76. let scale_y = -2.0 / viewport_size.1 as f32;
  77. let tex_mat: Matrix3<f32> = Matrix3::from_cols(
  78. vec3(marker_size.x as f32, 0.0, 0.0),
  79. vec3(0.0, marker_size.y as f32, 0.0),
  80. vec3(marker_offset.x as f32, marker_offset.y as f32, 1.0),
  81. );
  82. let screen_mat: Matrix3<f32> = Matrix3::from_cols(
  83. vec3(scale_x, 0.0, 0.0),
  84. vec3(0.0, scale_y, 0.0),
  85. vec3(-1.0, 1.0, 1.0),
  86. );
  87. let t1 = Point2::new(0.0f32, 0.0);
  88. let t2 = Point2::new(1.0f32, 0.0);
  89. let t3 = Point2::new(1.0f32, 1.0);
  90. let t4 = Point2::new(0.0f32, 1.0);
  91. let visible_rect = ScreenRect {
  92. x: -(marker_offset.x + marker_size.x),
  93. y: -(marker_offset.y + marker_size.y),
  94. width: f64::from(viewport_size.0) + marker_size.x,
  95. height: f64::from(viewport_size.1) + marker_size.y,
  96. };
  97. for map_pos in &self.positions {
  98. let screen_pos = {
  99. let mut sp = map_view.map_to_screen_coord(*map_pos);
  100. if snap_to_pixel {
  101. let topleft = map_view.map_to_screen_coord(MapCoord::new(0.0, 0.0));
  102. let mut snapped = topleft;
  103. snapped.snap_to_pixel();
  104. sp.x += snapped.x - topleft.x;
  105. sp.y += snapped.y - topleft.y;
  106. }
  107. sp
  108. };
  109. if !screen_pos.is_inside(&visible_rect) {
  110. continue;
  111. }
  112. let trans_mat: Matrix3<f32> = Matrix3::from_cols(
  113. vec3(0.0, 0.0, 0.0),
  114. vec3(0.0, 0.0, 0.0),
  115. vec3(screen_pos.x as f32, screen_pos.y as f32, 0.0),
  116. );
  117. let mat: Matrix3<f32> = screen_mat * (tex_mat + trans_mat);
  118. let p1: Point2<f32> = mat.transform_point(t1);
  119. let p2: Point2<f32> = mat.transform_point(t2);
  120. let p3: Point2<f32> = mat.transform_point(t3);
  121. let p4: Point2<f32> = mat.transform_point(t4);
  122. vertex_data.extend::<&[f32; 2]>(p1.as_ref());
  123. vertex_data.extend::<&[f32; 2]>(t1.as_ref());
  124. vertex_data.extend::<&[f32; 2]>(p2.as_ref());
  125. vertex_data.extend::<&[f32; 2]>(t2.as_ref());
  126. vertex_data.extend::<&[f32; 2]>(p3.as_ref());
  127. vertex_data.extend::<&[f32; 2]>(t3.as_ref());
  128. vertex_data.extend::<&[f32; 2]>(p1.as_ref());
  129. vertex_data.extend::<&[f32; 2]>(t1.as_ref());
  130. vertex_data.extend::<&[f32; 2]>(p3.as_ref());
  131. vertex_data.extend::<&[f32; 2]>(t3.as_ref());
  132. vertex_data.extend::<&[f32; 2]>(p4.as_ref());
  133. vertex_data.extend::<&[f32; 2]>(t4.as_ref());
  134. }
  135. self.buffer.set_data(cx, &vertex_data, vertex_data.len() / 4);
  136. self.buffer.draw(cx, &self.program, DrawMode::Triangles);
  137. }
  138. }