1 use integral_geometry::{Point, Rect, Size}; |
1 use integral_geometry::{GridIndex, Point, Rect, Size}; |
2 use land2d::Land2D; |
2 use land2d::Land2D; |
3 use vec2d::Vec2D; |
3 use vec2d::Vec2D; |
4 |
4 |
5 use super::gl::{ |
5 use super::gl::{ |
6 Buffer, InputElement, InputFormat, InputLayout, Shader, Texture2D, VariableBinding, |
6 Buffer, InputElement, InputFormat, InputLayout, Shader, Texture2D, VariableBinding, |
73 tile_draw_calls: Vec<DrawTile>, |
73 tile_draw_calls: Vec<DrawTile>, |
74 index_offset: u16, |
74 index_offset: u16, |
75 tile_shader: Shader, |
75 tile_shader: Shader, |
76 tile_layout: InputLayout, |
76 tile_layout: InputLayout, |
77 |
77 |
78 tile_width: u32, |
78 tile_size: Size, |
79 tile_height: u32, |
79 num_tile_x: usize, |
80 num_tile_x: i32, |
|
81 } |
80 } |
82 |
81 |
83 impl MapRenderer { |
82 impl MapRenderer { |
84 pub fn new(tile_width: u32, tile_height: u32) -> Self { |
83 pub fn new(tile_size: Size) -> Self { |
|
84 debug_assert!(tile_size.is_power_of_two()); |
|
85 |
85 let tile_shader = Shader::new( |
86 let tile_shader = Shader::new( |
86 VERTEX_SHADER, |
87 VERTEX_SHADER, |
87 Some(PIXEL_SHADER), |
88 Some(PIXEL_SHADER), |
88 &[ |
89 &[ |
89 VariableBinding::Attribute("Position", 0), |
90 VariableBinding::Attribute("Position", 0), |
91 VariableBinding::Sampler("Texture", 0), |
92 VariableBinding::Sampler("Texture", 0), |
92 ], |
93 ], |
93 ) |
94 ) |
94 .unwrap(); |
95 .unwrap(); |
95 |
96 |
|
97 let vertex_size = std::mem::size_of::<TileVertex>() as u32; |
96 let tile_layout = InputLayout::new(vec![ |
98 let tile_layout = InputLayout::new(vec![ |
97 // position |
99 // position |
98 InputElement { |
100 InputElement { |
99 shader_slot: 0, |
101 shader_slot: 0, |
100 buffer_slot: 0, |
102 buffer_slot: 0, |
101 format: InputFormat::Float(gl::FLOAT, false), |
103 format: InputFormat::Float(gl::FLOAT, false), |
102 components: 2, |
104 components: 2, |
103 stride: 20, |
105 stride: vertex_size, |
104 offset: 0, |
106 offset: 0, |
105 }, |
107 }, |
106 // uv |
108 // uv |
107 InputElement { |
109 InputElement { |
108 shader_slot: 1, |
110 shader_slot: 1, |
109 buffer_slot: 0, |
111 buffer_slot: 0, |
110 format: InputFormat::Float(gl::FLOAT, false), |
112 format: InputFormat::Float(gl::FLOAT, false), |
111 components: 3, |
113 components: 3, |
112 stride: 20, |
114 stride: vertex_size, |
113 offset: 8, |
115 offset: 8, |
114 }, |
116 }, |
115 ]); |
117 ]); |
116 |
118 |
117 MapRenderer { |
119 MapRenderer { |
126 |
128 |
127 tile_draw_calls: Vec::new(), |
129 tile_draw_calls: Vec::new(), |
128 tile_shader, |
130 tile_shader, |
129 tile_layout, |
131 tile_layout, |
130 |
132 |
131 tile_width, |
133 tile_size, |
132 tile_height, |
|
133 num_tile_x: 0, |
134 num_tile_x: 0, |
134 } |
135 } |
135 } |
136 } |
136 |
137 |
137 pub fn init(&mut self, land: &Vec2D<u32>) { |
138 pub fn init(&mut self, land: &Vec2D<u32>) { |
138 // clear tiles, but keep our textures for potential re-use |
139 // clear tiles, but keep our textures for potential re-use |
139 self.tiles.clear(); |
140 self.tiles.clear(); |
140 |
141 |
141 let tw = self.tile_width as usize; |
142 let tw = self.tile_size.width; |
142 let th = self.tile_height as usize; |
143 let th = self.tile_size.height; |
143 let lw = land.width(); |
144 let lw = land.width(); |
144 let lh = land.height(); |
145 let lh = land.height(); |
145 let num_tile_x = lw / tw + if lw % tw != 0 { 1 } else { 0 }; |
146 let num_tile_x = lw / tw; |
146 let num_tile_y = lh / th + if lh % th != 0 { 1 } else { 0 }; |
147 let num_tile_y = lh / th; |
147 |
148 |
148 self.num_tile_x = num_tile_x as i32; |
149 self.num_tile_x = num_tile_x; |
149 |
150 |
150 for y in 0..num_tile_y { |
151 for y in 0..num_tile_y { |
151 for x in 0..num_tile_x { |
152 for x in 0..num_tile_x { |
152 let idx = x + y * num_tile_x; |
153 let idx = x + y * num_tile_x; |
153 |
154 |
177 let texture_index = self.textures.len(); |
178 let texture_index = self.textures.len(); |
178 self.textures.push(texture); |
179 self.textures.push(texture); |
179 |
180 |
180 texture_index |
181 texture_index |
181 } else { |
182 } else { |
182 let texture_region = Rect::new( |
183 let texture_region = Rect::at_origin(self.tile_size); |
183 Point::new(0, 0), |
|
184 Point::new(self.tile_width as i32, self.tile_height as i32), |
|
185 ); |
|
186 |
184 |
187 self.textures[idx].update( |
185 self.textures[idx].update( |
188 texture_region, |
186 texture_region, |
189 data, |
187 data, |
190 stride, |
188 stride, |
196 |
194 |
197 let tile = MapTile { |
195 let tile = MapTile { |
198 texture_index: texture_index as u32, |
196 texture_index: texture_index as u32, |
199 |
197 |
200 // TODO: are there ever non-power of two textures? |
198 // TODO: are there ever non-power of two textures? |
201 width: self.tile_width, |
199 width: self.tile_size.width as u32, |
202 height: self.tile_height, |
200 height: self.tile_size.height as u32, |
203 }; |
201 }; |
204 self.tiles.push(tile); |
202 self.tiles.push(tile); |
205 } |
203 } |
206 } |
204 } |
207 } |
205 } |
213 self.tile_indices.clear(); |
211 self.tile_indices.clear(); |
214 self.tile_draw_calls.clear(); |
212 self.tile_draw_calls.clear(); |
215 self.index_offset = 0; |
213 self.index_offset = 0; |
216 |
214 |
217 for (idx, tile) in self.tiles.iter().enumerate() { |
215 for (idx, tile) in self.tiles.iter().enumerate() { |
218 let tile_x = idx as i32 % self.num_tile_x; |
216 let tile_x = idx % self.num_tile_x; |
219 let tile_y = idx as i32 / self.num_tile_x; |
217 let tile_y = idx / self.num_tile_x; |
220 let tile_w = self.tile_width as i32; |
218 let tile_w = self.tile_size.width; |
221 let tile_h = self.tile_height as i32; |
219 let tile_h = self.tile_size.width; |
222 |
220 |
223 let origin = Point::new(tile_x * tile_w, tile_y * tile_h); |
221 let origin = Point::new((tile_x * tile_w) as i32, (tile_y * tile_h) as i32); |
224 let tile_rect = Rect::new(origin, origin + Point::new(tile_w, tile_h)); |
222 let tile_rect = Rect::from_size(origin, self.tile_size); |
225 |
223 |
226 if viewport.intersects(&tile_rect) { |
224 if viewport.intersects(&tile_rect) { |
227 // lazy |
225 // lazy |
228 //dbg!(origin); |
226 //dbg!(origin); |
229 let tile_x = origin.x as f32; |
227 let tile_x = origin.x as f32; |
272 Some(&self.tile_index_buffer), |
270 Some(&self.tile_index_buffer), |
273 ); |
271 ); |
274 |
272 |
275 let ortho = { |
273 let ortho = { |
276 let l = viewport.left() as f32; |
274 let l = viewport.left() as f32; |
277 let r = viewport.right() as f32; |
275 let w = viewport.width() as f32; |
278 let b = viewport.bottom() as f32; |
276 let h = viewport.height() as f32; |
279 let t = viewport.top() as f32; |
277 let t = viewport.top() as f32; |
280 |
278 |
281 [ |
279 [ |
282 2f32 / (r - l), |
280 2f32 / w, |
283 0f32, |
281 0f32, |
284 0f32, |
282 0f32, |
285 0f32, |
283 0f32, |
286 0f32, |
284 0f32, |
287 2f32 / (t - b), |
285 2f32 / -h, |
288 0f32, |
286 0f32, |
289 0f32, |
287 0f32, |
290 0f32, |
288 0f32, |
291 0f32, |
289 0f32, |
292 0.5f32, |
290 0.5f32, |
293 0f32, |
291 0f32, |
294 (r + l) / (l - r), |
292 -(2.0 * l + w) / w, |
295 (t + b) / (b - t), |
293 (2.0 * t + h) / h, |
296 0.5f32, |
294 0.5f32, |
297 1f32, |
295 1f32, |
298 ] |
296 ] |
299 }; |
297 }; |
300 |
298 |