Johann Woelper 5 years ago
parent
commit
c535881c26
3 changed files with 401 additions and 214 deletions
  1. BIN
      landscape.blend
  2. 308 76
      out.json
  3. 93 138
      src/main.rs

BIN
landscape.blend


+ 308 - 76
out.json

@@ -1,17 +1,9 @@
 [
-    {
-        "name": "road-end-low",
-        "pos": [
-            -88.0,
-            -72.0,
-            0.0
-        ]
-    },
     {
         "name": "road-tjunction-low",
         "pos": [
             -88.0,
-            -64.0,
+            -240.0,
             0.0
         ]
     },
@@ -19,7 +11,7 @@
         "name": "road-straight-low",
         "pos": [
             -80.0,
-            -64.0,
+            -240.0,
             0.0
         ]
     },
@@ -27,15 +19,15 @@
         "name": "building-office-small",
         "pos": [
             -96.0,
-            -72.0,
+            -248.0,
             0.0
         ]
     },
     {
-        "name": "road-corner-low",
+        "name": "road-corner-low-tl",
         "pos": [
-            -72.0,
-            -72.0,
+            -48.0,
+            -208.0,
             0.0
         ]
     },
@@ -43,7 +35,7 @@
         "name": "road-crossing-low",
         "pos": [
             -72.0,
-            -64.0,
+            -240.0,
             0.0
         ]
     },
@@ -51,7 +43,7 @@
         "name": "grass",
         "pos": [
             -80.0,
-            -56.0,
+            -232.0,
             0.0
         ]
     },
@@ -59,7 +51,7 @@
         "name": "road-straight-low",
         "pos": [
             -64.0,
-            -64.0,
+            -240.0,
             0.0
         ]
     },
@@ -67,15 +59,15 @@
         "name": "road-straight-low",
         "pos": [
             -56.0,
-            -64.0,
+            -240.0,
             0.0
         ]
     },
     {
-        "name": "road-straight-low",
+        "name": "road-straight-low-rot",
         "pos": [
-            -48.0,
-            -64.0,
+            -72.0,
+            -232.0,
             0.0
         ]
     },
@@ -83,23 +75,23 @@
         "name": "road-straight-low-rot",
         "pos": [
             -72.0,
-            -56.0,
+            -224.0,
             0.0
         ]
     },
     {
-        "name": "road-straight-low-rot",
+        "name": "grass",
         "pos": [
-            -72.0,
-            -48.0,
+            -80.0,
+            -224.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -80.0,
-            -48.0,
+            -64.0,
+            -232.0,
             0.0
         ]
     },
@@ -107,31 +99,103 @@
         "name": "grass",
         "pos": [
             -64.0,
+            -224.0,
+            0.0
+        ]
+    },
+    {
+        "name": "grass",
+        "pos": [
             -56.0,
+            -224.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-straight-low-rot",
+        "pos": [
+            -88.0,
+            -232.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-straight-low-rot",
+        "pos": [
+            -88.0,
+            -224.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-straight-low",
+        "pos": [
+            -96.0,
+            -240.0,
+            0.0
+        ]
+    },
+    {
+        "name": "building-office-small",
+        "pos": [
+            -56.0,
+            -248.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -64.0,
-            -48.0,
+            -96.0,
+            -232.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -56.0,
-            -48.0,
+            -96.0,
+            -224.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-end-low",
+        "pos": [
+            -104.0,
+            -240.0,
+            0.0
+        ]
+    },
+    {
+        "name": "grass",
+        "pos": [
+            -104.0,
+            -232.0,
+            0.0
+        ]
+    },
+    {
+        "name": "grass",
+        "pos": [
+            -104.0,
+            -224.0,
+            0.0
+        ]
+    },
+    {
+        "name": "grass",
+        "pos": [
+            -104.0,
+            -248.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -48.0,
             -56.0,
+            -216.0,
             0.0
         ]
     },
@@ -139,7 +203,7 @@
         "name": "grass",
         "pos": [
             -48.0,
-            -48.0,
+            -216.0,
             0.0
         ]
     },
@@ -147,31 +211,31 @@
         "name": "grass",
         "pos": [
             -64.0,
-            -72.0,
+            -216.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -48.0,
-            -72.0,
+            -56.0,
+            -256.0,
             0.0
         ]
     },
     {
-        "name": "road-straight-low-rot",
+        "name": "road-straight-low",
         "pos": [
-            -88.0,
-            -56.0,
+            -80.0,
+            -216.0,
             0.0
         ]
     },
     {
-        "name": "road-straight-low-rot",
+        "name": "road-crossing-low",
         "pos": [
             -88.0,
-            -48.0,
+            -216.0,
             0.0
         ]
     },
@@ -179,7 +243,31 @@
         "name": "road-straight-low",
         "pos": [
             -96.0,
-            -64.0,
+            -216.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-end-low",
+        "pos": [
+            -104.0,
+            -216.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-straight-low-rot",
+        "pos": [
+            -88.0,
+            -208.0,
+            0.0
+        ]
+    },
+    {
+        "name": "building-office-small",
+        "pos": [
+            -80.0,
+            -208.0,
             0.0
         ]
     },
@@ -187,119 +275,239 @@
         "name": "building-office-small",
         "pos": [
             -56.0,
+            -232.0,
+            0.0
+        ]
+    },
+    {
+        "name": "building-office-small",
+        "pos": [
+            -96.0,
+            -208.0,
+            0.0
+        ]
+    },
+    {
+        "name": "grass",
+        "pos": [
+            -64.0,
+            -248.0,
+            0.0
+        ]
+    },
+    {
+        "name": "grass",
+        "pos": [
             -72.0,
+            -208.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -96.0,
-            -56.0,
+            -104.0,
+            -208.0,
             0.0
         ]
     },
     {
         "name": "grass",
+        "pos": [
+            -112.0,
+            -216.0,
+            0.0
+        ]
+    },
+    {
+        "name": "building-office-small",
+        "pos": [
+            -112.0,
+            -240.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-corner-low-tr",
+        "pos": [
+            -64.0,
+            -208.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-straight-low-rot",
         "pos": [
             -96.0,
-            -48.0,
+            -192.0,
             0.0
         ]
     },
     {
-        "name": "road-end-low",
+        "name": "grass",
         "pos": [
             -104.0,
+            -200.0,
+            0.0
+        ]
+    },
+    {
+        "name": "building-office-small",
+        "pos": [
+            -56.0,
+            -184.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-straight-low-rot",
+        "pos": [
+            -48.0,
+            -200.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-straight-low",
+        "pos": [
+            -56.0,
+            -192.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-corner-low-lb",
+        "pos": [
+            -48.0,
+            -192.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-corner-low-br",
+        "pos": [
             -64.0,
+            -192.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-straight-low-rot",
+        "pos": [
+            -64.0,
+            -200.0,
             0.0
         ]
     },
     {
         "name": "road-straight-low",
         "pos": [
-            -80.0,
+            -56.0,
+            -208.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-corner-low-lb",
+        "pos": [
             -72.0,
+            -216.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -104.0,
             -56.0,
+            -200.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -104.0,
             -48.0,
+            -184.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -104.0,
-            -72.0,
+            -40.0,
+            -192.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -56.0,
             -40.0,
+            -208.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -48.0,
-            -40.0,
+            -72.0,
+            -200.0,
             0.0
         ]
     },
     {
         "name": "grass",
         "pos": [
-            -64.0,
-            -40.0,
+            -72.0,
+            -192.0,
             0.0
         ]
     },
     {
         "name": "grass",
+        "pos": [
+            -64.0,
+            -184.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-crossing-low",
+        "pos": [
+            -88.0,
+            -200.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-corner-low-tr",
         "pos": [
             -96.0,
-            -80.0,
+            -200.0,
             0.0
         ]
     },
     {
-        "name": "grass",
+        "name": "road-corner-low-tl",
         "pos": [
-            -56.0,
             -80.0,
+            -200.0,
             0.0
         ]
     },
     {
-        "name": "road-corner-low-rot",
+        "name": "road-straight-low-rot",
         "pos": [
-            -72.0,
-            -40.0,
+            -88.0,
+            -192.0,
             0.0
         ]
     },
     {
-        "name": "road-straight-low",
+        "name": "road-straight-low-rot",
         "pos": [
             -80.0,
-            -40.0,
+            -192.0,
             0.0
         ]
     },
@@ -307,55 +515,79 @@
         "name": "road-crossing-low",
         "pos": [
             -88.0,
-            -40.0,
+            -184.0,
             0.0
         ]
     },
     {
-        "name": "road-straight-low",
+        "name": "road-corner-low-lb",
+        "pos": [
+            -80.0,
+            -184.0,
+            0.0
+        ]
+    },
+    {
+        "name": "road-corner-low-br",
         "pos": [
             -96.0,
-            -40.0,
+            -184.0,
             0.0
         ]
     },
     {
-        "name": "road-end-low",
+        "name": "building-office-small",
+        "pos": [
+            -72.0,
+            -184.0,
+            0.0
+        ]
+    },
+    {
+        "name": "building-office-small",
         "pos": [
             -104.0,
-            -40.0,
+            -184.0,
             0.0
         ]
     },
     {
         "name": "road-straight-low-rot",
+        "pos": [
+            -72.0,
+            -248.0,
+            0.0
+        ]
+    },
+    {
+        "name": "grass",
         "pos": [
             -88.0,
-            -32.0,
+            -248.0,
             0.0
         ]
     },
     {
-        "name": "building-office-small",
+        "name": "grass",
         "pos": [
             -80.0,
-            -32.0,
+            -248.0,
             0.0
         ]
     },
     {
         "name": "building-office-small",
         "pos": [
-            -56.0,
-            -56.0,
+            -39.6363639831543,
+            -200.0,
             0.0
         ]
     },
     {
         "name": "building-office-small",
         "pos": [
-            -96.0,
-            -32.0,
+            -104.0,
+            -192.0,
             0.0
         ]
     }

+ 93 - 138
src/main.rs

@@ -39,6 +39,23 @@ impl V3 {
         ]
     }
 
+    fn rotated_neighbors(self, axis: u8,) -> [V3; 6] {
+
+    //      [2]
+    //   [1][S][0]
+    //      [3]
+
+        [
+            self,
+            self,
+            self,
+            self,
+            self,
+            self,
+        ]
+    }
+
+
     fn offsets(self) -> [V3; 6] {
         [
             V3::new(1, 0, 0),
@@ -56,7 +73,6 @@ impl fmt::Debug for V3 {
         write!(f, "V[{},{},{}]", self.x*8, self.y*8, self.z*8)
     }
 }
-
 impl Add<V3> for V3 {
     type Output = V3;
     fn add(self, other: V3) -> V3 {
@@ -67,7 +83,6 @@ impl Add<V3> for V3 {
         }
     }
 }
-
 impl Add<i32> for V3 {
     type Output = V3;
     fn add(self, other: i32) -> V3 {
@@ -78,7 +93,6 @@ impl Add<i32> for V3 {
         }
     }
 }
-
 impl Mul<i32> for V3 {
     type Output = V3;
     fn mul(self, other: i32) -> V3 {
@@ -89,7 +103,6 @@ impl Mul<i32> for V3 {
         }
     }
 }
-
 impl Neg<> for V3 {
     type Output = V3;
     fn neg(self) -> V3 {
@@ -100,7 +113,6 @@ impl Neg<> for V3 {
         }
     }
 }
-
 impl<'a, 'b> Add<&'b V3> for &'a V3 {
     type Output = V3;
 
@@ -112,7 +124,6 @@ impl<'a, 'b> Add<&'b V3> for &'a V3 {
         }
     }
 }
-
 impl<'a> Mul<i32> for &'a V3 {
     type Output = V3;
 
@@ -124,8 +135,6 @@ impl<'a> Mul<i32> for &'a V3 {
         }
     }
 }
-
-
 impl<'a> Neg<> for &'a V3 {
     type Output = V3;
 
@@ -138,31 +147,14 @@ impl<'a> Neg<> for &'a V3 {
     }
 }
 
-// impl Sub<V3> for  V3 {
-//     type Output = V3;
-//     fn sub(self, other: V3) -> V3 {
-//         V3 {
-//             x: self.x - other.x,
-//             y: self.y - other.y,
-//             z: self.z - other.z,
-//         }
-//     }
-// }
-
-// #[derive(Clone, Debug)]
-// struct Voxel {
-//     id: String,
-//     // adjacency: HashMap<&'static str, u16>,
-//     adjacency: HashMap<V3, Vec<String>>,
-//     // offsets: [V3; 6]
-
-// }
 
 /// A graphics tile as ex- or imported from a 3d program
 #[derive(Clone, Debug, Serialize, Deserialize)]
 struct GfxTile {
     name: String,
     pos: Vec<f32>,
+    #[serde(default)]
+    rot: Vec<f32>
 }
 
 fn unitized_grid(vol: &HashMap<V3, String>, divisor: i32) -> HashMap<V3, String> {
@@ -238,23 +230,17 @@ fn load_export(path: &'static str) -> HashMap<V3, String> {
     let loaded_tiles: Vec<GfxTile> = serde_json::from_reader(reader).expect("Could not parse JSON");
     loaded_tiles
         .iter()
-        .map(|x| {
+        .map(|t| {
+            dbg!(&t);
             (
-                V3::new(x.pos[0] as i32, x.pos[1] as i32, x.pos[2] as i32),
-                x.name.clone(),
+                V3::new(t.pos[0] as i32, t.pos[1] as i32, t.pos[2] as i32),
+                t.name.clone(),
             )
         })
         .collect()
 }
 
-// fn get_adjacent_tiles(grid: &HashMap<V3, String>, training_data: &HashMap<String, HashMap<V3, Vec<String>>>) -> HashMap<V3, String> {
-//     let mut adjacents: HashMap<V3, String> = HashMap::new();
 
-//     for (pos, tile) in grid {
-
-//     }
-//     adjacents
-// }
 
 fn get_unsolved_neighbors(cell: &V3, grid: &HashMap<V3, String>) -> Vec<V3> {
     let mut neighbors = vec![];
@@ -267,16 +253,45 @@ fn get_unsolved_neighbors(cell: &V3, grid: &HashMap<V3, String>) -> Vec<V3> {
     neighbors
 }
 
-fn template_meets_constraints(constraint: &HashMap<V3, String>, template: &HashMap<V3, Vec<String>>) -> bool {
-    
+fn solve(constraint: &HashMap<V3, String>, training_data: &HashMap<String, HashMap<V3, Vec<String>>>) -> Option<String> {
     
-    for (c_pos, c_name) in constraint {
-        // let _x = template.get(&c_pos).map(|x| x.contains(c_name));
-        if let Some(possible_tiles) = template.get(&c_pos) {
-            
+ 
+    let mut valid_templates = vec![];
+    for template in training_data {
+        
+        let c: Vec<bool> = constraint
+        .iter()
+        .map(|(pos, name)| template.1.get(&pos).map(|x| x.contains(name)) )
+        .filter(|e| e.is_some())
+        .map(|e| e.unwrap())
+        .collect();
+
+        if c.is_empty() {
+            valid_templates.push(None);
+        } else {
+            if c.iter().all(|x| x == &true) {
+                valid_templates.push(Some(template.0))
+            } 
         }
+    
+        // valid_templates.push(c);
+
     }
-    true
+
+
+    let valid_tiles: Vec<_> = valid_templates.iter().filter(|x| x.is_some()).map(|x| x.unwrap()).collect();
+
+    // This was not solvable
+    if valid_tiles.is_empty() {
+        return None
+    } else {
+
+        Some(valid_tiles.choose(&mut rand::thread_rng()).unwrap().to_string())
+        // Some("grass".to_string())
+    }
+    
+
+
 }
 
 fn wfc_solver(
@@ -288,100 +303,51 @@ fn wfc_solver(
 
     for (pos, _name) in new_grid.clone() {
         for unsolved_neighbor in get_unsolved_neighbors(&pos, &new_grid) {
-            println!("Unsolved {:?}", unsolved_neighbor);
+
+            debug!("Unsolved {:?}", unsolved_neighbor);
+            
             let mut contraint_map: HashMap<V3, String> = HashMap::new();
             
             for tile_neighbor in &unsolved_neighbor.offsets() {
                 let abs_neighbor_pos = &unsolved_neighbor + tile_neighbor;
 
                 if let Some(tn) = new_grid.get(&abs_neighbor_pos) {
-                    println!("\tNeighbor {:?} exists, is {}", abs_neighbor_pos, tn);
-                    // println!("\tTraining data for {} = {:?}", tn, training_data.get(tn).unwrap());
-                    
+                    debug!("\tNeighbor {:?} exists, is {}. Inserting as constraint.", abs_neighbor_pos, tn);
                     contraint_map.insert(tile_neighbor.clone(), tn.to_string());
-                    // if let Some(constraints) = training_data.get(tn).unwrap().get(&-tile_neighbor) {
-                    //     // println!("\t{} points to me, accepts {:?}", tn, constraints);
-                    //     println!(
-                    //         "\t\tlooking up in {} {:?}",
-                    //         tn, tile_neighbor
-                    //     );
-                    //     let cs = constraints.choose(&mut rand::thread_rng()).unwrap();
-                    //     println!("\t\tAdded a randomly chosen constraint: {:?}", cs);
-                    //     // new_grid.insert(unsolved_neighbor, cs.to_string());
-                    //     contraint_map.insert(tile_neighbor.clone(), cs.to_string());
-                        
-                    // } else {
-                    //     // println!("\t\tNo training data in tile {} at offset {:?}", tn, tile_neighbor);
-                    // }
-                    
                 }
             }
-            // Constraint map is ready here
-            // println!("All constraints: {:?}", contraint_map);
-            let num_constraints = contraint_map.len();
-            
-            println!("\tSolving {} contraints in {:?}", num_constraints, contraint_map );
+            // Constraint map is ready here      
+            debug!("\tSolving {} contraints in {:?}", contraint_map.len(), contraint_map );
+
+
+
+            match solve(&contraint_map, &training_data) {
+                Some(tile) => {
+                    if tile == "BACKTRACK" {
+                        for n in unsolved_neighbor.neighbors().iter(){
+                               new_grid.remove(&n);
+                        }
+                    } else {
+                        new_grid.insert(unsolved_neighbor, tile);
+                    }
+                },
+                None => {
+                    // for n in unsolved_neighbor.neighbors().iter(){
+                    //     new_grid.remove(&n);
+                    // }
+                }
+
+            };
+
+
 
-            
-            //let mut compatible = 0;
-            for (template_name, compatible_tiles) in training_data {
-                
-                //if compatible == num_constraints {break;}
-                println!("\t\tProbing template {:?}", template_name );
-                let _compat = template_meets_constraints(&contraint_map, compatible_tiles);
-                
-
-                //new_grid.insert(unsolved_neighbor, template_tile.to_string());
-
-                // // TODO: iterate through all combos at all the constraint positions
-                // for (p, constraint) in &contraint_map {
-                //     println!("\t\t\tWill {:?} {} fit?", p, constraint );
-                //     if let Some(tiles_for_this_pos) = compatible_tiles.get(&p) {
-                //         println!("\t\t\tAt the above pos, this is what the template offers: {:?}", tiles_for_this_pos );
-                //         if tiles_for_this_pos.contains(&constraint) {
-                //             compatible += 1;
-                //             if compatible == num_constraints {
-                //                 println!("\tSolved with {}.", template_tile);
-                //                 new_grid.insert(unsolved_neighbor, template_tile.to_string());
-                //                 break;
-                //             }
-                //         }
-                //     }
-                // }
-                
-
-                // println!("{}", compatible);
-            }
 
             
-            // for (pos, tilename) in contraint_map {
-            //     println!("\tSolving {} constraint", tilename );
-            //     // Now find a suitable tile in training data
-            //     let mut compatible = 0;
-            //     for (template_tile, compatible_tiles) in training_data {
-            //         if let Some(tiles_for_this_pos) = compatible_tiles.get(&pos) {
-            //             if tiles_for_this_pos.contains(&tilename) {
-            //                 println!("\t{} template supports {} @{:?}", template_tile, tilename, pos, );
-            //                 compatible += 1;
-            //                 if compatible == num_constraints {
-            //                     println!("\t{} fits all criteria. Locking in at {:?}", template_tile, unsolved_neighbor*8);
-            //                     new_grid.insert(unsolved_neighbor, template_tile.to_string());
-
-            //                     break;
-
-            //                 }
-            //             }
-
-            //         }
-            //     }
-
-            // }
-
-            // println!("Training data: {:?}", trained_data_for_this_tile);
+           
         }
     }
 
-    println!("grid: {:?}", new_grid);
+    // println!("grid: {:?}", new_grid);
 
     new_grid
 }
@@ -402,31 +368,20 @@ fn main() {
 
     let training_data = train_volume(&import_volume);
     info!("Training done: {} tiles", training_data.len());
-    // for (tilename, adjacency_map) in training_data {
-    //     println!("\n{}", tilename);
-    //     for (pos, fitting_tiles) in adjacency_map{
-    //         println!("{:?}{:?}", pos, fitting_tiles);
-    //     }
-    // }
-
-    // let new_grid: HashMap<V3, String> = HashMap::new();
+
     let mut base_map: HashMap<V3, String> = HashMap::new();
+
     // init start conditions
     base_map.insert(V3::new(0, 0, 0), String::from("grass"));
 
-    for i in 1..3 {
+    for i in 1..8 {
         info!(
-            "=========================== Iteration {} ===========================\n\n\n",
+            "=========================== Iteration {} ===========================",
             i
         );
         base_map = wfc_solver(&training_data, base_map);
     }
 
-    //base_map = wfc_solver(&training_data, base_map);
-    //base_map = wfc_solver(&training_data, base_map);
-
-    // dbg!(&vol);
-    // let mut adj_map: HashMap<String, Adjacency> = HashMap::new();
 
     let mut export = vec![];
     for (p, n) in &base_map {