فهرست منبع

prep work for constrains

Johann Woelper 6 سال پیش
والد
کامیت
99b81c4db0
3فایلهای تغییر یافته به همراه101 افزوده شده و 71 حذف شده
  1. BIN
      landscape.blend
  2. 24 0
      out.json
  3. 77 71
      src/main.rs

BIN
landscape.blend


+ 24 - 0
out.json

@@ -254,5 +254,29 @@
             -72.0,
             0.0
         ]
+    },
+    {
+        "name": "grass",
+        "pos": [
+            -56.0,
+            -40.0,
+            0.0
+        ]
+    },
+    {
+        "name": "grass",
+        "pos": [
+            -48.0,
+            -40.0,
+            0.0
+        ]
+    },
+    {
+        "name": "grass",
+        "pos": [
+            -64.0,
+            -40.0,
+            0.0
+        ]
     }
 ]

+ 77 - 71
src/main.rs

@@ -2,24 +2,24 @@
 extern crate serde_derive;
 extern crate serde;
 extern crate serde_json;
-use std::io::BufWriter;
-use std::io::BufReader;
 use std::fs::File;
+use std::io::BufReader;
+use std::io::BufWriter;
 // use std::ops::{Add, Sub, Div};
-use std::ops::{Add, Mul};
 use std::collections::HashMap;
-#[macro_use] extern crate log;
+use std::ops::{Add, Mul};
+#[macro_use]
+extern crate log;
 extern crate simplelog;
+use rand::seq::SliceRandom;
 use simplelog::*;
 use std::fmt;
-use rand::seq::SliceRandom; 
-
 
 #[derive(Clone, Serialize, Deserialize, Copy, Eq, PartialEq, Hash)]
 struct V3 {
     x: i32,
     y: i32,
-    z: i32
+    z: i32,
 }
 
 impl V3 {
@@ -27,40 +27,37 @@ impl V3 {
         V3 { x: x, y: y, z: z }
     }
 
-    fn neighbors(self) -> [V3;6] {
+    fn neighbors(self) -> [V3; 6] {
         let o = self.offsets();
         [
-            self+o[0],
-            self+o[1],
-            self+o[2],
-            self+o[3],
-            self+o[4],
-            self+o[5]
+            self + o[0],
+            self + o[1],
+            self + o[2],
+            self + o[3],
+            self + o[4],
+            self + o[5],
         ]
     }
 
-    fn offsets(self) -> [V3;6] {
+    fn offsets(self) -> [V3; 6] {
         [
-            V3::new(1,0,0),
-            V3::new(-1,0,0),
-            V3::new(0,1,0),
-            V3::new(0,-1,0),
-            V3::new(0,0,1),
-            V3::new(0,0,-1),
+            V3::new(1, 0, 0),
+            V3::new(-1, 0, 0),
+            V3::new(0, 1, 0),
+            V3::new(0, -1, 0),
+            V3::new(0, 0, 1),
+            V3::new(0, 0, -1),
         ]
     }
 }
 
-
-
-
 impl fmt::Debug for V3 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "V[{},{},{}]", self.x, self.y, self.z)
     }
 }
 
-impl Add<V3> for  V3 {
+impl Add<V3> for V3 {
     type Output = V3;
     fn add(self, other: V3) -> V3 {
         V3 {
@@ -71,7 +68,7 @@ impl Add<V3> for  V3 {
     }
 }
 
-impl Add<i32> for  V3 {
+impl Add<i32> for V3 {
     type Output = V3;
     fn add(self, other: i32) -> V3 {
         V3 {
@@ -82,7 +79,7 @@ impl Add<i32> for  V3 {
     }
 }
 
-impl Mul<i32> for  V3 {
+impl Mul<i32> for V3 {
     type Output = V3;
     fn mul(self, other: i32) -> V3 {
         V3 {
@@ -128,7 +125,6 @@ impl<'a> Mul<i32> for &'a V3 {
 //     }
 // }
 
-
 // #[derive(Clone, Debug)]
 // struct Voxel {
 //     id: String,
@@ -145,15 +141,22 @@ struct GfxTile {
     pos: Vec<f32>,
 }
 
-
-
-
 fn unitized_grid(vol: &HashMap<V3, String>, divisor: i32) -> HashMap<V3, String> {
-    vol.iter().map(|(k,v)| (V3{x: k.x/divisor, y: k.y/divisor, z: k.z/divisor},v.clone())).collect()
+    vol.iter()
+        .map(|(k, v)| {
+            (
+                V3 {
+                    x: k.x / divisor,
+                    y: k.y / divisor,
+                    z: k.z / divisor,
+                },
+                v.clone(),
+            )
+        })
+        .collect()
 }
 
-
-fn guess_gridsize(vol: &HashMap<V3, String>) -> i32{
+fn guess_gridsize(vol: &HashMap<V3, String>) -> i32 {
     let mut x_positions: Vec<i32> = vol.iter().map(|(k, _v)| k.x).collect();
     let mut y_positions: Vec<i32> = vol.iter().map(|(k, _v)| k.y).collect();
     x_positions.sort();
@@ -164,7 +167,7 @@ fn guess_gridsize(vol: &HashMap<V3, String>) -> i32{
     let mut last: Option<i32> = None;
     for px in x_positions {
         if let Some(l) = last {
-            let delta = px.abs() - l;  
+            let delta = px.abs() - l;
             let c = dist_count.entry(delta.abs()).or_insert(1);
             *c += 1;
         }
@@ -182,19 +185,15 @@ fn guess_gridsize(vol: &HashMap<V3, String>) -> i32{
 
     // dbg!(&grid);
     grid
-
 }
 
 fn train_volume(vol: &HashMap<V3, String>) -> HashMap<String, HashMap<V3, Vec<String>>> {
-    
     let mut trained: HashMap<String, HashMap<V3, Vec<String>>> = HashMap::new();
 
     for (pos, tilename) in vol {
         // lookup neighbors
 
-        let tile = trained.entry(tilename.clone()).or_insert(
-            HashMap::new()
-        );
+        let tile = trained.entry(tilename.clone()).or_insert(HashMap::new());
 
         for p_o in pos.offsets().iter() {
             let p_n = p_o + pos;
@@ -203,26 +202,27 @@ fn train_volume(vol: &HashMap<V3, String>) -> HashMap<String, HashMap<V3, Vec<St
                     neighbor_tile.push(neighbor.clone());
                 } else {
                     tile.insert(p_o.clone(), vec![neighbor.clone()]);
-                }  
+                }
             }
         }
     }
     trained
 }
 
-
 fn load_export(path: &'static str) -> HashMap<V3, String> {
     let reader = BufReader::new(File::open(path).unwrap());
-    let loaded_tiles: Vec<GfxTile> = serde_json::from_reader(reader).unwrap();
+    let loaded_tiles: Vec<GfxTile> = serde_json::from_reader(reader).expect("Could not parse JSON");
     loaded_tiles
         .iter()
         .map(|x| {
-            (V3::new(x.pos[0] as i32, x.pos[1] as i32, x.pos[2] as i32), x.name.clone())
+            (
+                V3::new(x.pos[0] as i32, x.pos[1] as i32, x.pos[2] as i32),
+                x.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();
 
@@ -243,46 +243,50 @@ fn get_unsolved_neighbors(cell: &V3, grid: &HashMap<V3, String>) -> Vec<V3> {
     neighbors
 }
 
-
-
-fn wfc_solver(training_data: &HashMap<String, HashMap<V3, Vec<String>>>, base_map: HashMap<V3, String>) -> HashMap<V3, String> {
+fn wfc_solver(
+    training_data: &HashMap<String, HashMap<V3, Vec<String>>>,
+    base_map: HashMap<V3, String>,
+) -> HashMap<V3, String> {
     let mut new_grid = base_map;
-    
 
-
-    for (pos, name) in new_grid.clone() {
+    for (pos, _name) in new_grid.clone() {
         for unsolved_neighbor in get_unsolved_neighbors(&pos, &new_grid) {
+            println!("Unsolved {:?}", unsolved_neighbor);
             for tile_neighbor in &unsolved_neighbor.offsets() {
-                if let Some(tn) = new_grid.get(&(&unsolved_neighbor+tile_neighbor)) {
+                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());
+                    let mut contraint_map: HashMap<V3, String> = HashMap::new();
+
                     if let Some(constraints) = training_data.get(tn).unwrap().get(tile_neighbor) {
                         // println!("\t{} points to me, accepts {:?}", tn, constraints);
-                        println!("Solving {:?} - looking into neighbors", unsolved_neighbor);
+                        println!(
+                            "\t\tSolving {:?} - looking into neighbors",
+                            unsolved_neighbor
+                        );
                         let cs = constraints.choose(&mut rand::thread_rng()).unwrap();
-                        println!("\tchose {:?}", cs);
+                        println!("\t\tchose {:?}", cs);
                         new_grid.insert(unsolved_neighbor, cs.to_string());
-
+                    } else {
+                        println!("\t\tNo training data in tile {} at offset {:?}", tn, tile_neighbor);
                     }
                 }
-
             }
 
             // println!("Training data: {:?}", trained_data_for_this_tile);
-
         }
-
     }
 
-
     println!("grid: {:?}", new_grid);
 
     new_grid
 }
 
 fn main() {
-
     let _ = simplelog::SimpleLogger::init(LevelFilter::Info, Config::default());
 
-
     let mut import_volume: HashMap<V3, String> = HashMap::new();
     let imported_tiles = load_export("out.json");
     let gridsize = guess_gridsize(&imported_tiles);
@@ -290,14 +294,12 @@ fn main() {
     let imported_tiles = unitized_grid(&imported_tiles, gridsize);
     info!("Tiles imported: {}", imported_tiles.len());
 
-
     for (pos, tile) in imported_tiles {
         import_volume.insert(pos, tile);
     }
 
     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{
@@ -309,21 +311,25 @@ fn main() {
     let mut base_map: HashMap<V3, String> = HashMap::new();
     // init start conditions
     base_map.insert(V3::new(10, 0, 0), String::from("grass"));
-    
-    base_map = wfc_solver(&training_data, base_map);
-    base_map = wfc_solver(&training_data, base_map);
-    base_map = wfc_solver(&training_data, base_map);
+
+    for i in 1..3 {
+        info!(
+            "=========================== Iteration {} ===========================\n\n\n",
+            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 {
-        export.push((p*gridsize,n));
+        export.push((p * gridsize, n));
     }
     let writer = BufWriter::new(File::create("map.json").unwrap());
     serde_json::to_writer_pretty(writer, &export).unwrap();
-
 }
-
-