| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- #[macro_use]
- 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::ops::{Add, Sub, Div};
- use std::collections::HashMap;
- // use nalgebra::Vector3;
- #[macro_use] extern crate log;
- extern crate simplelog;
- use simplelog::*;
- #[derive(Clone, Debug, Serialize, Deserialize, Copy, Eq, PartialEq, Hash)]
- struct V3 {
- x: i32,
- y: i32,
- z: i32
- }
- impl V3 {
- fn new(x: i32, y: i32, z: i32) -> V3 {
- V3 { x: x, y: y, z: z }
- }
- 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]
- ]
- }
- 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),
- ]
- }
- }
- impl Add<V3> for V3 {
- type Output = V3;
- fn add(self, other: V3) -> V3 {
- V3 {
- x: self.x + other.x,
- y: self.y + other.y,
- z: self.z + other.z,
- }
- }
- }
- impl Add<i32> for V3 {
- type Output = V3;
- fn add(self, other: i32) -> V3 {
- V3 {
- x: self.x + other,
- y: self.y + other,
- z: self.z + other,
- }
- }
- }
- impl<'a, 'b> Add<&'b V3> for &'a V3 {
- type Output = V3;
- fn add(self, other: &'b V3) -> V3 {
- V3 {
- x: self.x + other.x,
- y: self.y + other.y,
- z: self.z + other.z,
- }
- }
- }
- // 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>,
- }
- 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()
- }
- fn guess_gridsize(vol: &HashMap<V3, String>) -> i32{
- let mut x_positions: Vec<i32> = vol.iter().map(|(k,v)| k.x).collect();
- x_positions.sort();
- x_positions.dedup();
- let mut dist_count: HashMap<i32, i32> = HashMap::new();
- let mut last: Option<i32> = None;
- for px in x_positions {
- if let Some(l) = last {
- let delta = px.abs() - l;
- let c = dist_count.entry(delta.abs()).or_insert(1);
- *c += 1;
- }
- last = Some(px.abs());
- }
- let mut grid = 1;
- let mut maxcount = 0;
- for (size, count) in dist_count {
- if count > maxcount {
- grid = size;
- maxcount = count;
- }
- }
- // 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()
- );
- for p_o in pos.offsets().iter() {
- let p_n = p_o + pos;
- if let Some(neighbor) = vol.get(&p_n) {
- if let Some(neighbor_tile) = tile.get_mut(&p_o) {
- 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();
- 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())
- })
- .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![];
- for n in &cell.neighbors() {
- if !grid.contains_key(n) {
- neighbors.push(n.clone());
- }
- }
- neighbors
- }
- fn wfc_solver(training_data: HashMap<String, HashMap<V3, Vec<String>>>) -> HashMap<V3, String> {
- let mut new_grid: HashMap<V3, String> = HashMap::new();
-
- // init start conditions
- new_grid.insert(V3::new(10, 0, 0), String::from("grass"));
- for (pos, name) in &new_grid {
- for unsolved_neighbor in get_unsolved_neighbors(pos, &new_grid) {
- println!("Solving {:?} (next to {})", unsolved_neighbor, name);
- let trained_data_for_this_tile = training_data.get(name).unwrap();
- }
- }
- 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);
- info!("Detected grid size: {}", gridsize);
- 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{
- // println!("{:?}{:?}", pos, fitting_tiles);
- // }
- // }
- let new_grid: HashMap<V3, String> = HashMap::new();
- wfc_solver(training_data);
- // dbg!(&vol);
- // let mut adj_map: HashMap<String, Adjacency> = HashMap::new();
- }
|