rust/landgen/src/wavefront_collapse/generator.rs
branchtransitional_engine
changeset 15954 9502611bffc1
parent 15953 d46ad15c6dec
child 15955 b0e8cc72bfef
equal deleted inserted replaced
15953:d46ad15c6dec 15954:9502611bffc1
    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 
    98                     for value in line.chunks_exact(a) {
    99                     for value in line.chunks_exact(a) {
    99                         print!("{:?},", value);
   100                         print!("{:?},", value);
   100                         *tiles_image_pixels
   101                         *tiles_image_pixels
   101                             .next()
   102                             .next()
   102                             .expect("vec2d size matching image dimensions") =
   103                             .expect("vec2d size matching image dimensions") =
   103                             if value[0] == 0u8 {
   104                             if value[0] == 0u8 { zero } else { basic };
   104                                 zero
       
   105                             } else {
       
   106                                 basic
       
   107                             };
       
   108                     }
   105                     }
   109                 }
   106                 }
   110             }
   107             }
   111         }
   108         }
   112 
   109 
   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     }
   227                 bottom,
   226                 bottom,
   228                 left,
   227                 left,
   229             });
   228             });
   230         }
   229         }
   231 
   230 
   232         let mut wfc = WavefrontCollapse::default();
   231         let mut wfc = WavefrontCollapse::new(self.template.wrap);
   233         wfc.set_rules(rules);
   232         wfc.set_rules(rules);
   234 
   233 
   235         let wfc_size = if let Some(first_tile) = tiles.first() {
   234         let wfc_size = if let Some(first_tile) = tiles.first() {
   236             let tile_size = first_tile.size();
   235             let tile_size = first_tile.size();
   237 
   236 
   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(&parameters.zero)
   263                                         *tile.get(tile_row, tile_column).unwrap_or(&parameters.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 }