25 |
25 |
26 #[derive(Clone)] |
26 #[derive(Clone)] |
27 pub struct TileDescription { |
27 pub struct TileDescription { |
28 pub name: String, |
28 pub name: String, |
29 pub edges: EdgesDescription, |
29 pub edges: EdgesDescription, |
30 pub is_negative: bool, |
30 pub is_negative: Option<bool>, |
31 pub can_flip: bool, |
31 pub can_flip: Option<bool>, |
32 pub can_mirror: bool, |
32 pub can_mirror: Option<bool>, |
33 pub can_rotate90: bool, |
33 pub can_rotate90: Option<bool>, |
34 pub can_rotate180: bool, |
34 pub can_rotate180: Option<bool>, |
35 pub can_rotate270: bool, |
35 pub can_rotate270: Option<bool>, |
36 } |
36 } |
37 |
37 |
38 #[derive(Clone)] |
38 #[derive(Clone)] |
39 pub struct TemplateDescription { |
39 pub struct TemplateDescription { |
40 pub size: Size, |
40 pub size: Size, |
41 pub tiles: Vec<TileDescription>, |
41 pub tiles: Vec<TileDescription>, |
|
42 pub wrap: bool, |
42 } |
43 } |
43 |
44 |
44 pub struct WavefrontCollapseLandGenerator { |
45 pub struct WavefrontCollapseLandGenerator { |
45 pub template: TemplateDescription, |
46 pub template: TemplateDescription, |
46 } |
47 } |
74 let info = reader.next_frame(&mut buf).unwrap(); |
75 let info = reader.next_frame(&mut buf).unwrap(); |
75 let bytes = &buf[..info.buffer_size()]; |
76 let bytes = &buf[..info.buffer_size()]; |
76 |
77 |
77 let mut tiles_image_pixels = tiles_image.as_mut_slice().iter_mut(); |
78 let mut tiles_image_pixels = tiles_image.as_mut_slice().iter_mut(); |
78 |
79 |
79 let (zero, basic) = if tile_description.is_negative { |
80 let (zero, basic) = if tile_description.is_negative.unwrap_or_default() { |
80 (parameters.basic(), parameters.zero()) |
81 (parameters.basic(), parameters.zero()) |
81 } else { |
82 } else { |
82 (parameters.zero(), parameters.basic()) |
83 (parameters.zero(), parameters.basic()) |
83 }; |
84 }; |
84 |
85 |
140 left_edge.clone(), |
137 left_edge.clone(), |
141 ); |
138 ); |
142 |
139 |
143 result.push(tile.clone()); |
140 result.push(tile.clone()); |
144 |
141 |
145 if tile_description.can_flip { |
142 if tile_description.can_flip.unwrap_or_default() { |
146 result.push(tile.flipped()); |
143 result.push(tile.flipped()); |
147 } |
144 } |
148 if tile_description.can_mirror { |
145 if tile_description.can_mirror.unwrap_or_default() { |
149 result.push(tile.mirrored()); |
146 result.push(tile.mirrored()); |
150 } |
147 } |
151 if tile_description.can_flip && tile_description.can_mirror { |
148 if tile_description.can_flip.unwrap_or_default() |
|
149 && tile_description.can_mirror.unwrap_or_default() |
|
150 { |
152 result.push(tile.mirrored().flipped()); |
151 result.push(tile.mirrored().flipped()); |
153 } |
152 } |
154 |
153 |
155 if tile_description.can_rotate90 { |
154 if tile_description.can_rotate90.unwrap_or_default() { |
156 result.push(tile.rotated90()); |
155 result.push(tile.rotated90()); |
157 } |
156 } |
158 if tile_description.can_rotate180 { |
157 if tile_description.can_rotate180.unwrap_or_default() { |
159 result.push(tile.rotated180()); |
158 result.push(tile.rotated180()); |
160 } |
159 } |
161 if tile_description.can_rotate270 { |
160 if tile_description.can_rotate270.unwrap_or_default() { |
162 result.push(tile.rotated270()); |
161 result.push(tile.rotated270()); |
163 } |
162 } |
164 |
163 |
165 Ok(result) |
164 Ok(result) |
166 } |
165 } |
244 }; |
243 }; |
245 |
244 |
246 wfc.generate_map(&wfc_size, |_| {}, random_numbers); |
245 wfc.generate_map(&wfc_size, |_| {}, random_numbers); |
247 |
246 |
248 let mut result = land2d::Land2D::new(&self.template.size, parameters.zero); |
247 let mut result = land2d::Land2D::new(&self.template.size, parameters.zero); |
|
248 let offset_y = result.height() - result.play_height(); |
|
249 let offset_x = (result.width() - result.play_width()) / 2; |
249 |
250 |
250 for row in 0..wfc_size.height { |
251 for row in 0..wfc_size.height { |
251 for column in 0..wfc_size.width { |
252 for column in 0..wfc_size.width { |
252 if let Some(Tile::Numbered(tile_index)) = wfc.grid().get(row, column) { |
253 if let Some(Tile::Numbered(tile_index)) = wfc.grid().get(row, column) { |
253 let tile = &tiles[*tile_index]; |
254 let tile = &tiles[*tile_index]; |
254 |
255 |
255 for tile_row in 0..tile.size().height { |
256 for tile_row in 0..tile.size().height { |
256 for tile_column in 0..tile.size().width { |
257 for tile_column in 0..tile.size().width { |
257 result.map( |
258 result.map( |
258 (row * tile.size().height + tile_row) as i32, |
259 (row * tile.size().height + tile_row + offset_y) as i32, |
259 (column * tile.size().width + tile_column) as i32, |
260 (column * tile.size().width + tile_column + offset_x) as i32, |
260 |p| { |
261 |p| { |
261 *p = |
262 *p = |
262 *tile.get(tile_row, tile_column).unwrap_or(¶meters.zero) |
263 *tile.get(tile_row, tile_column).unwrap_or(¶meters.zero) |
263 }, |
264 }, |
264 ); |
265 ); |
269 } |
270 } |
270 |
271 |
271 result |
272 result |
272 } |
273 } |
273 } |
274 } |
274 |
|
275 #[cfg(test)] |
|
276 mod tests { |
|
277 use super::WavefrontCollapseLandGenerator; |
|
278 use crate::{LandGenerationParameters, LandGenerator}; |
|
279 use integral_geometry::Size; |
|
280 use std::fs::File; |
|
281 use std::io::BufWriter; |
|
282 use std::path::Path; |
|
283 |
|
284 #[test] |
|
285 fn test_generation() { |
|
286 let wfc_gen = WavefrontCollapseLandGenerator::new(&Size::new(2048, 1024)); |
|
287 let landgen_params = LandGenerationParameters::new(0u32, 0xff000000u32, 0, true, true); |
|
288 let land = wfc_gen.generate_land( |
|
289 &landgen_params, |
|
290 &mut [0u32, 1u32, 3u32, 5u32, 7u32, 11u32].into_iter().cycle(), |
|
291 ); |
|
292 |
|
293 let path = Path::new(r"output.png"); |
|
294 let file = File::create(path).unwrap(); |
|
295 let ref mut w = BufWriter::new(file); |
|
296 |
|
297 let mut encoder = png::Encoder::new(w, land.width() as u32, land.height() as u32); // Width is 2 pixels and height is 1. |
|
298 encoder.set_color(png::ColorType::Rgba); |
|
299 encoder.set_depth(png::BitDepth::Eight); |
|
300 encoder.set_source_gamma(png::ScaledFloat::from_scaled(45455)); // 1.0 / 2.2, scaled by 100000 |
|
301 encoder.set_source_gamma(png::ScaledFloat::new(1.0 / 2.2)); // 1.0 / 2.2, unscaled, but rounded |
|
302 let source_chromaticities = png::SourceChromaticities::new( |
|
303 // Using unscaled instantiation here |
|
304 (0.31270, 0.32900), |
|
305 (0.64000, 0.33000), |
|
306 (0.30000, 0.60000), |
|
307 (0.15000, 0.06000), |
|
308 ); |
|
309 encoder.set_source_chromaticities(source_chromaticities); |
|
310 let mut writer = encoder.write_header().unwrap(); |
|
311 |
|
312 writer.write_image_data(land.raw_pixel_bytes()).unwrap(); // Save |
|
313 } |
|
314 } |
|