rust/landgen/src/wavefront_collapse/generator.rs
branchtransitional_engine
changeset 15918 9bd828451d77
parent 15917 60b5639cc3a5
child 15919 659c92124c26
equal deleted inserted replaced
15917:60b5639cc3a5 15918:9bd828451d77
     5 use png::Decoder;
     5 use png::Decoder;
     6 use std::collections::HashSet;
     6 use std::collections::HashSet;
     7 use std::fs::File;
     7 use std::fs::File;
     8 use std::io::BufReader;
     8 use std::io::BufReader;
     9 
     9 
    10 pub struct WavefrontCollapseLandGenerator {}
    10 pub struct WavefrontCollapseLandGenerator {
       
    11     pub size: Size,
       
    12 }
    11 
    13 
    12 impl WavefrontCollapseLandGenerator {
    14 impl WavefrontCollapseLandGenerator {
    13     pub fn new() -> Self {
    15     pub fn new(size: &Size) -> Self {
    14         Self {}
    16         Self { size: *size }
    15     }
    17     }
    16 
    18 
    17     pub fn load_template<T: Copy + PartialEq + Default>(
    19     pub fn load_template<T: Copy + PartialEq + Default>(
    18         &self,
    20         &self,
    19         parameters: &LandGenerationParameters<T>,
    21         parameters: &LandGenerationParameters<T>,
    47                         parameters.basic
    49                         parameters.basic
    48                     };
    50                     };
    49             }
    51             }
    50         }
    52         }
    51 
    53 
    52         let top_edge = Edge::new("edge".to_owned(), false);
    54         let top_edge = Edge::new("ef".to_owned(), false);
    53         let right_edge = Edge::new("edge".to_owned(), false);
    55         let right_edge = top_edge.reversed();
    54         let bottom_edge = Edge::new("edge".to_owned(), false);
    56         let bottom_edge = Edge::new("ee".to_owned(), true);
    55         let left_edge = Edge::new("edge".to_owned(), false);
    57         let left_edge = bottom_edge.clone();
    56 
    58 
    57         let tile =
    59         let tile =
    58             TileImage::<T, String>::new(tiles_image, top_edge, right_edge, bottom_edge, left_edge);
    60             TileImage::<T, String>::new(tiles_image, top_edge, right_edge, bottom_edge, left_edge);
    59 
    61 
    60         result.push(tile.clone());
    62         result.push(tile.clone());
    61         result.push(tile.mirrored());
    63         result.push(tile.rotated90());
       
    64         result.push(tile.rotated180());
       
    65         result.push(tile.rotated270());
    62 
    66 
    63         result
    67         result
    64     }
    68     }
    65 }
    69 }
    66 
    70 
    80             let mut bottom = default_connection.clone();
    84             let mut bottom = default_connection.clone();
    81             let mut left = default_connection.clone();
    85             let mut left = default_connection.clone();
    82             let mut top = default_connection.clone();
    86             let mut top = default_connection.clone();
    83 
    87 
    84             for p in 0..i {
    88             for p in 0..i {
    85                 if tiles[p].left_edge() == tile.right_edge() {
    89                 if tiles[p].left_edge().is_compatible(tile.right_edge()) {
    86                     rules[p].left.insert(Tile::Numbered(i));
    90                     rules[p].left.insert(Tile::Numbered(i));
    87                     right.insert(Tile::Numbered(p));
    91                     right.insert(Tile::Numbered(p));
    88                 }
    92                 }
    89 
    93 
    90                 if tiles[p].right_edge() == tile.left_edge() {
    94                 if tiles[p].right_edge().is_compatible(tile.left_edge()) {
    91                     rules[p].right.insert(Tile::Numbered(i));
    95                     rules[p].right.insert(Tile::Numbered(i));
    92                     left.insert(Tile::Numbered(p));
    96                     left.insert(Tile::Numbered(p));
    93                 }
    97                 }
    94 
    98 
    95                 if tiles[p].top_edge() == tile.bottom_edge() {
    99                 if tiles[p].top_edge().is_compatible(tile.bottom_edge()) {
    96                     rules[p].top.insert(Tile::Numbered(i));
   100                     rules[p].top.insert(Tile::Numbered(i));
    97                     bottom.insert(Tile::Numbered(p));
   101                     bottom.insert(Tile::Numbered(p));
    98                 }
   102                 }
    99 
   103 
   100                 if tiles[p].bottom_edge() == tile.top_edge() {
   104                 if tiles[p].bottom_edge().is_compatible(tile.top_edge()) {
   101                     rules[p].bottom.insert(Tile::Numbered(i));
   105                     rules[p].bottom.insert(Tile::Numbered(i));
   102                     top.insert(Tile::Numbered(p));
   106                     top.insert(Tile::Numbered(p));
   103                 }
   107                 }
   104             }
   108             }
   105 
   109 
   113         }
   117         }
   114 
   118 
   115         let mut wfc = WavefrontCollapse::default();
   119         let mut wfc = WavefrontCollapse::default();
   116         wfc.set_rules(rules);
   120         wfc.set_rules(rules);
   117 
   121 
   118         wfc.generate_map(&Size::new(40, 20), |_| {}, random_numbers);
   122         let wfc_size = if let Some(first_tile) = tiles.first() {
       
   123             let tile_size = first_tile.size();
       
   124 
       
   125             Size::new(
       
   126                 self.size.width / tile_size.width,
       
   127                 self.size.height / tile_size.height,
       
   128             )
       
   129         } else {
       
   130             Size::new(1, 1)
       
   131         };
       
   132 
       
   133         wfc.generate_map(&wfc_size, |_| {}, random_numbers);
   119 
   134 
   120         let grid = wfc.grid();
   135         let grid = wfc.grid();
   121 
   136 
   122         for r in 0..grid.height() {
   137         for r in 0..grid.height() {
   123             for c in 0..grid.width() {
   138             for c in 0..grid.width() {
   125             }
   140             }
   126 
   141 
   127             println!();
   142             println!();
   128         }
   143         }
   129 
   144 
   130         todo!("build result")
   145         let mut result = land2d::Land2D::new(&self.size, parameters.zero);
       
   146 
       
   147         for row in 0..wfc_size.height {
       
   148             for column in 0..wfc_size.width {
       
   149                 if let Some(Tile::Numbered(tile_index)) = wfc.grid().get(row, column) {
       
   150                     let tile = &tiles[*tile_index];
       
   151 
       
   152                     for tile_row in 0..tile.size().height {
       
   153                         for tile_column in 0..tile.size().width {
       
   154                             result.map(
       
   155                                 (row * tile.size().height + tile_row) as i32,
       
   156                                 (column * tile.size().width + tile_column) as i32,
       
   157                                 |p| {
       
   158                                     *p =
       
   159                                         *tile.get(tile_row, tile_column).unwrap_or(&parameters.zero)
       
   160                                 },
       
   161                             );
       
   162                         }
       
   163                     }
       
   164                 }
       
   165             }
       
   166         }
       
   167 
       
   168         result
   131     }
   169     }
   132 }
   170 }
   133 
   171 
   134 #[cfg(test)]
   172 #[cfg(test)]
   135 mod tests {
   173 mod tests {
   136     use super::WavefrontCollapseLandGenerator;
   174     use super::WavefrontCollapseLandGenerator;
   137     use crate::{LandGenerationParameters, LandGenerator};
   175     use crate::{LandGenerationParameters, LandGenerator};
   138     use integral_geometry::Size;
   176     use integral_geometry::Size;
       
   177     use std::fs::File;
       
   178     use std::io::BufWriter;
       
   179     use std::path::Path;
   139     use vec2d::Vec2D;
   180     use vec2d::Vec2D;
   140 
   181 
   141     #[test]
   182     #[test]
   142     fn test_generation() {
   183     fn test_generation() {
   143         let wfc_gen = WavefrontCollapseLandGenerator::new();
   184         let wfc_gen = WavefrontCollapseLandGenerator::new(&Size::new(2048, 1024));
   144         let landgen_params = LandGenerationParameters::new(0u8, 255u8, 0, true, true);
   185         let landgen_params = LandGenerationParameters::new(0u32, 0xff000000u32, 0, true, true);
   145         wfc_gen.generate_land(&landgen_params, &mut std::iter::repeat(1u32));
   186         let land = wfc_gen.generate_land(&landgen_params, &mut std::iter::repeat(0u32));
   146     }
   187 
   147 }
   188         let path = Path::new(r"output.png");
       
   189         let file = File::create(path).unwrap();
       
   190         let ref mut w = BufWriter::new(file);
       
   191 
       
   192         let mut encoder = png::Encoder::new(w, land.width() as u32, land.height() as u32); // Width is 2 pixels and height is 1.
       
   193         encoder.set_color(png::ColorType::Rgba);
       
   194         encoder.set_depth(png::BitDepth::Eight);
       
   195         encoder.set_source_gamma(png::ScaledFloat::from_scaled(45455)); // 1.0 / 2.2, scaled by 100000
       
   196         encoder.set_source_gamma(png::ScaledFloat::new(1.0 / 2.2)); // 1.0 / 2.2, unscaled, but rounded
       
   197         let source_chromaticities = png::SourceChromaticities::new(
       
   198             // Using unscaled instantiation here
       
   199             (0.31270, 0.32900),
       
   200             (0.64000, 0.33000),
       
   201             (0.30000, 0.60000),
       
   202             (0.15000, 0.06000),
       
   203         );
       
   204         encoder.set_source_chromaticities(source_chromaticities);
       
   205         let mut writer = encoder.write_header().unwrap();
       
   206 
       
   207         writer.write_image_data(land.raw_pixel_bytes()).unwrap(); // Save
       
   208     }
       
   209 }