WfcModule

Struct WfcModule 

Source
pub struct WfcModule<TBitSet>
where TBitSet: BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> + BitUnion<Output = TBitSet>,
{ pub north_neighbours: TBitSet, pub south_neighbours: TBitSet, pub east_neighbours: TBitSet, pub west_neighbours: TBitSet, }
Expand description

A building block of WFC, which lets user to set adjacency rules for tiles

Each neighbours bitset are expected to hold indices of neighbour modules which will be hold in a &WfcModule used by WfcContext

Fields§

§north_neighbours: TBitSet

North neighbouring modules

§south_neighbours: TBitSet

South neighbouring modules

§east_neighbours: TBitSet

East neighbouring modules

§west_neighbours: TBitSet

West neighbouring modules

Implementations§

Source§

impl<TBitSet> WfcModule<TBitSet>
where TBitSet: BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> + BitUnion<Output = TBitSet>,

Source

pub fn new() -> Self

A constructor of a module with all neighbouring sets empty

Examples found in repository?
examples/wang_corner_carpet.rs (line 116)
69    pub async fn new(w: usize, h: usize) -> Self {
70        let InternalGlContext {
71            quad_context: ctx, ..
72        } = unsafe { get_internal_gl() };
73
74        let texture_bytes = load_file("assets/wang_4_corner.png").await.unwrap();
75
76        let img = image::load_from_memory(&texture_bytes[..])
77            .unwrap_or_else(|e| panic!("{}", e))
78            .to_rgba8();
79
80        let img_w = img.width();
81        let img_h = img.height();
82
83        let texture = Texture2D::from_miniquad_texture(
84            miniquad::Texture::from_data_and_format(
85                ctx,
86                &img.into_raw(),
87                TextureParams {
88                    format: TextureFormat::RGBA8,
89                    wrap: TextureWrap::Clamp,
90                    filter: FilterMode::Nearest,
91                    width: img_w,
92                    height: img_h
93                }
94            )
95        );
96
97        let tiles = (0..=255)
98            .map(|idx| {
99                let width = 32;
100                let height = 32;
101                (
102                    idx as u8,
103                    SubRect {
104                        x: (idx % 16) * width,
105                        y: (idx / 16) * height,
106                        width,
107                        height
108                    }
109                )
110            })
111            .collect::<Vec<_>>();
112
113        let modules = tiles
114            .iter()
115            .map(|tile| {
116                let mut module: WfcModule<CustomBitSet> = WfcModule::new();
117                for i in 0..tiles.len() {
118                    let other_tile = &tiles[i];
119                    if get_north_west(tile.0) == get_south_west(other_tile.0) &&
120                        get_north_east(tile.0) == get_south_east(other_tile.0) {
121                        module.add_north_neighbour(i);
122                    }
123                    if get_south_west(tile.0) == get_north_west(other_tile.0) &&
124                        get_south_east(tile.0) == get_north_east(other_tile.0) {
125                        module.add_south_neighbour(i);
126                    }
127                    if get_north_west(tile.0) == get_north_east(other_tile.0) &&
128                        get_south_west(tile.0) == get_south_east(other_tile.0) {
129                        module.add_west_neighbour(i);
130                    }
131                    if get_north_east(tile.0) == get_north_west(other_tile.0) &&
132                        get_south_east(tile.0) == get_south_west(other_tile.0) {
133                        module.add_east_neighbour(i);
134                    }
135                }
136                module
137            })
138            .collect::<Vec<_>>();
139
140        Self {
141            w,
142            h,
143            tile_width: 32,
144            tile_height: 32,
145            tiles,
146            modules,
147            texture,
148            map_data: vec![0; w*h]
149        }
150    }
More examples
Hide additional examples
examples/dungeon.rs (line 318)
144    pub async fn new(w: usize, h: usize) -> Self {
145        let InternalGlContext {
146            quad_context: ctx, ..
147        } = unsafe { get_internal_gl() };
148
149        let dungeon_bytes = load_file("assets/dungeon_tiles.png").await.unwrap();
150
151        let img = image::load_from_memory(&dungeon_bytes[..])
152            .unwrap_or_else(|e| panic!("{}", e))
153            .to_rgba8();
154
155        let img_w = img.width();
156        let img_h = img.height();
157
158        let texture = Texture2D::from_miniquad_texture(
159            miniquad::Texture::from_data_and_format(
160                ctx,
161                &img.into_raw(),
162                TextureParams {
163                    format: TextureFormat::RGBA8,
164                    wrap: TextureWrap::Clamp,
165                    filter: FilterMode::Nearest,
166                    width: img_w,
167                    height: img_h
168                }
169            )
170        );
171
172        let tiles_bytes = load_file("assets/dungeon_tiles.ron").await.unwrap();
173        let dungeon_tiles: DungeonTiles = from_reader(&tiles_bytes[..]).unwrap();
174
175        let mut tiles = Vec::new();
176        for (kind_code, subrects) in dungeon_tiles.wang_4_corner_tiles.iter() {
177            tiles.push(Tile {
178                kind: TileKind::Wang4Corner(*kind_code),
179                subrects: subrects.clone(),
180                neighbours_east: Vec::new(),
181                neighbours_west: Vec::new(),
182                neighbours_north: Vec::new(),
183                neighbours_south: Vec::new()
184            });
185        }
186        // We need to be sure that zero tile is always a "void" tile, so we doing an extra sort step
187        tiles.sort_by(|lhs, rhs| {
188            match (lhs.kind, rhs.kind) {
189                (TileKind::Wang4Corner(kind_lhs), TileKind::Wang4Corner(kind_rhs)) => kind_lhs.cmp(&kind_rhs),
190                _ => Ordering::Equal
191            }
192        });
193
194        for i in 0..tiles.len() {
195            let current_kind = tiles[i].kind;
196            for j in 0..tiles.len() {
197                let candidate_kind = tiles[j].kind;
198                let (matches_north, matches_south, matches_east, matches_west) = {
199                    match (current_kind, candidate_kind) {
200                        (TileKind::Wang4Corner(current), TileKind::Wang4Corner(candidate)) => {
201                            (
202                                get_north_east(current) == get_south_east(candidate) &&
203                                    get_north_west(current) == get_south_west(candidate),
204
205                                get_south_east(current) == get_north_east(candidate) &&
206                                    get_south_west(current) == get_north_west(candidate),
207
208                                get_north_east(current) == get_north_west(candidate) &&
209                                    get_south_east(current) == get_south_west(candidate),
210
211                                get_north_west(current) == get_north_east(candidate) &&
212                                    get_south_west(current) == get_south_east(candidate),
213                            )
214                        },
215                        _ => continue
216                    }
217                };
218                if matches_east {
219                    tiles[i].neighbours_east.push(candidate_kind);
220                }
221                if matches_west {
222                    tiles[i].neighbours_west.push(candidate_kind);
223                }
224                if matches_north {
225                    tiles[i].neighbours_north.push(candidate_kind);
226                }
227                if matches_south {
228                    tiles[i].neighbours_south.push(candidate_kind);
229                }
230            }
231        }
232
233        //Add bridges:
234        {
235            let bridge_tiles_offset = tiles.len();
236            tiles.extend_from_slice(&dungeon_tiles.extra_tiles[..]);
237
238            let mut bridge_match_queue_south = VecDeque::new();
239            let mut bridge_match_queue_north = VecDeque::new();
240            let mut bridge_match_queue_east = VecDeque::new();
241            let mut bridge_match_queue_west = VecDeque::new();
242
243            for bridge_tile in &tiles[bridge_tiles_offset..] {
244                for south_neighbour in bridge_tile.neighbours_south.iter() {
245                    if let TileKind::Wang4Corner(kind) = south_neighbour {
246                        for i in 0..bridge_tiles_offset {
247                            match tiles[i].kind {
248                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
249                                    bridge_match_queue_south.push_back((bridge_tile.kind, i))
250                                },
251                                _ => ()
252                            };
253                        }
254                    }
255                }
256                for north_neighbour in bridge_tile.neighbours_north.iter() {
257                    if let TileKind::Wang4Corner(kind) = north_neighbour {
258                        for i in 0..bridge_tiles_offset {
259                            match tiles[i].kind {
260                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
261                                    bridge_match_queue_north.push_back((bridge_tile.kind, i))
262                                },
263                                _ => ()
264                            };
265                        }
266                    }
267                }
268                for east_neighbour in bridge_tile.neighbours_east.iter() {
269                    if let TileKind::Wang4Corner(kind) = east_neighbour {
270                        for i in 0..bridge_tiles_offset {
271                            match tiles[i].kind {
272                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
273                                    bridge_match_queue_east.push_back((bridge_tile.kind, i))
274                                },
275                                _ => ()
276                            };
277                        }
278                    }
279                }
280                for west_neighbour in bridge_tile.neighbours_west.iter() {
281                    if let TileKind::Wang4Corner(kind) = west_neighbour {
282                        for i in 0..bridge_tiles_offset {
283                            match tiles[i].kind {
284                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
285                                    bridge_match_queue_west.push_back((bridge_tile.kind, i))
286                                },
287                                _ => ()
288                            };
289                        }
290                    }
291                }
292            }
293
294            while !bridge_match_queue_south.is_empty() {
295                let next_match = bridge_match_queue_south.pop_front().unwrap();
296                tiles[next_match.1].neighbours_north.push(next_match.0);
297            }
298
299            while !bridge_match_queue_north.is_empty() {
300                let next_match = bridge_match_queue_north.pop_front().unwrap();
301                tiles[next_match.1].neighbours_south.push(next_match.0);
302            }
303
304            while !bridge_match_queue_east.is_empty() {
305                let next_match = bridge_match_queue_east.pop_front().unwrap();
306                tiles[next_match.1].neighbours_west.push(next_match.0);
307            }
308
309            while !bridge_match_queue_west.is_empty() {
310                let next_match = bridge_match_queue_west.pop_front().unwrap();
311                tiles[next_match.1].neighbours_east.push(next_match.0);
312            }
313        }
314
315        let modules = tiles
316            .iter()
317            .map(|tile| {
318                let mut module: WfcModule<CustomBitSet> = WfcModule::new();
319                for i in 0..tiles.len() {
320                    if tile.neighbours_north.contains(&tiles[i].kind) {
321                        module.add_north_neighbour(i);
322                    }
323                    if tile.neighbours_south.contains(&tiles[i].kind) {
324                        module.add_south_neighbour(i);
325                    }
326                    if tile.neighbours_west.contains(&tiles[i].kind) {
327                        module.add_west_neighbour(i);
328                    }
329                    if tile.neighbours_east.contains(&tiles[i].kind) {
330                        module.add_east_neighbour(i);
331                    }
332                }
333                module
334            })
335            .collect::<Vec<_>>();
336        
337        Self {
338            w,
339            h,
340            tile_width: dungeon_tiles.tile_width,
341            tile_height: dungeon_tiles.tile_height,
342            tiles,
343            modules,
344            texture,
345            map_data: vec![(0, 0); w*h]
346        }
347    }
examples/summer_garden.rs (line 330)
183    pub async fn new(w: usize, h: usize, draw_scale: f32) -> Self {
184        let InternalGlContext {
185            quad_context: ctx, ..
186        } = unsafe { get_internal_gl() };
187
188        let texture_bytes = load_file("assets/reduced_wang_scheme.png").await.unwrap();
189
190        let img = image::load_from_memory(&texture_bytes[..])
191            .unwrap_or_else(|e| panic!("{}", e))
192            .to_rgba8();
193
194        let img_w = img.width();
195        let img_h = img.height();
196
197        let texture = Texture2D::from_miniquad_texture(
198            miniquad::Texture::from_data_and_format(
199                ctx,
200                &img.into_raw(),
201                TextureParams {
202                    format: TextureFormat::RGBA8,
203                    wrap: TextureWrap::Clamp,
204                    filter: FilterMode::Nearest,
205                    width: img_w,
206                    height: img_h
207                }
208            )
209        );
210
211        let atlas_bytes = load_file("assets/reduced_wang_scheme.ron").await.unwrap();
212        let atlas: SummerGardenAtlas = from_reader(&atlas_bytes[..]).unwrap();
213
214        let mut tile_sides = Vec::new();
215        let mut neighbour_strategies = Vec::new();
216        let mut tiles = Vec::new();
217
218        {
219            for tile_cfg in atlas.terrain_tile_configs.iter() {
220                for pattern in &[
221                    &atlas.reduced_wang_patterns[..],
222                    &atlas.extended_set_1_patterns_north_west[..],
223                    &atlas.extended_set_1_patterns_north_east[..],
224                    &atlas.extended_set_1_patterns_south_west[..],
225                    &atlas.extended_set_1_patterns_south_east[..],
226                    &atlas.extended_set_2_patterns_north_west[..],
227                    &atlas.extended_set_2_patterns_north_east[..],
228                    &atlas.extended_set_2_patterns_south_west[..],
229                    &atlas.extended_set_2_patterns_south_east[..],
230                ] {
231                    tile_sides.extend(
232                        pattern.iter().map(
233                            |pattern| {
234                                TileSides {
235                                    north_west: match pattern.north_west {
236                                        TileKind::Inner => { tile_cfg.inner_type }
237                                        TileKind::Outer => { tile_cfg.outer_type }
238                                    },
239                                    north_east: match pattern.north_east {
240                                        TileKind::Inner => { tile_cfg.inner_type }
241                                        TileKind::Outer => { tile_cfg.outer_type }
242                                    },
243                                    south_west: match pattern.south_west {
244                                        TileKind::Inner => { tile_cfg.inner_type }
245                                        TileKind::Outer => { tile_cfg.outer_type }
246                                    },
247                                    south_east: match pattern.south_east {
248                                        TileKind::Inner => { tile_cfg.inner_type }
249                                        TileKind::Outer => { tile_cfg.outer_type }
250                                    }
251                                }
252                            }
253                        )
254                    );
255                }
256                for j in 0..4 {
257                    for i in 0..4 {
258                        tiles.push(SubRect{
259                            x: i * 32 + tile_cfg.x_offset,
260                            y: j * 32 + tile_cfg.y_offset,
261                            width: 32,
262                            height: 32
263                        })
264                    }
265                }
266                for jj in 0..2 {
267                    for ii in 0..2 {
268                        for j in 0..2 {
269                            for i in 0..2 {
270                                tiles.push(SubRect{
271                                    x: (i + ii * 2) * 32 + tile_cfg.x_offset + 256,
272                                    y: (j + jj * 2) * 32 + tile_cfg.y_offset,
273                                    width: 32,
274                                    height: 32
275                                })
276                            }
277                        }
278                    }
279                }
280                for jj in 0..2 {
281                    for ii in 0..2 {
282                        for j in 0..2 {
283                            for i in 0..2 {
284                                tiles.push(SubRect{
285                                    x: (i + ii * 2) * 32 + tile_cfg.x_offset,
286                                    y: (j + jj * 2) * 32 + tile_cfg.y_offset + 256,
287                                    width: 32,
288                                    height: 32
289                                })
290                            }
291                        }
292                    }
293                }
294                neighbour_strategies.extend_from_slice(&atlas.reduced_wang_neighbour_strategy[..]);
295                for _ in 0..8 {
296                    neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_2_x_2[..]);
297                }
298            }
299            tile_sides.extend_from_slice(&atlas.vertical_bridge_sides[..]);
300            tile_sides.extend_from_slice(&atlas.horizontal_bridge_sides[..]);
301            for j in 0..3 {
302                for i in 0..3 {
303                    tiles.push(SubRect{
304                        x: i * 32 + 256,
305                        y: j * 32 + 256,
306                        width: 32,
307                        height: 32
308                    })
309                }
310            }
311            for j in 0..3 {
312                for i in 0..3 {
313                    tiles.push(SubRect{
314                        x: i * 32 + 256 + 96,
315                        y: j * 32 + 256,
316                        width: 32,
317                        height: 32
318                    })
319                }
320            }
321            neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
322            neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
323
324            assert_eq!(tile_sides.len(), neighbour_strategies.len());
325        }
326
327        let mut modules = Vec::new();
328        for i in 0..tile_sides.len() {
329            let current_sides = tile_sides[i];
330            let mut module: WfcModule<CustomBitSet> = WfcModule::new();
331            match neighbour_strategies[i].north {
332                NeighbourKind::WangCorners => {
333                    for j in 0..tile_sides.len() {
334                        if neighbour_strategies[j].south != NeighbourKind::WangCorners {
335                            continue;
336                        }
337                        if tile_sides[j].south_west == current_sides.north_west &&
338                            tile_sides[j].south_east == current_sides.north_east {
339                            module.add_north_neighbour(j);
340                        }
341                    }
342                }
343                NeighbourKind::RelOffset(offset) => {
344                    let new_offset = (i as i32 + offset) as usize;
345                    module.add_north_neighbour(new_offset);
346                }
347            }
348            match neighbour_strategies[i].south {
349                NeighbourKind::WangCorners => {
350                    for j in 0..tile_sides.len() {
351                        if neighbour_strategies[j].north != NeighbourKind::WangCorners {
352                            continue;
353                        }
354                        if tile_sides[j].north_west == current_sides.south_west &&
355                            tile_sides[j].north_east == current_sides.south_east {
356                            module.add_south_neighbour(j);
357                        }
358                    }
359                }
360                NeighbourKind::RelOffset(offset) => {
361                    let new_offset = (i as i32 + offset) as usize;
362                    module.add_south_neighbour(new_offset);
363                }
364            }
365            match neighbour_strategies[i].east {
366                NeighbourKind::WangCorners => {
367                    for j in 0..tile_sides.len() {
368                        if neighbour_strategies[j].west != NeighbourKind::WangCorners {
369                            continue;
370                        }
371                        if tile_sides[j].north_west == current_sides.north_east &&
372                            tile_sides[j].south_west == current_sides.south_east {
373                            module.add_east_neighbour(j);
374                        }
375                    }
376                }
377                NeighbourKind::RelOffset(offset) => {
378                    let new_offset = (i as i32 + offset) as usize;
379                    module.add_east_neighbour(new_offset);
380                }
381            }
382            match neighbour_strategies[i].west {
383                NeighbourKind::WangCorners => {
384                    for j in 0..tile_sides.len() {
385                        if neighbour_strategies[j].east != NeighbourKind::WangCorners {
386                            continue;
387                        }
388                        if tile_sides[j].north_east == current_sides.north_west &&
389                            tile_sides[j].south_east == current_sides.south_west {
390                            module.add_west_neighbour(j);
391                        }
392                    }
393                }
394                NeighbourKind::RelOffset(offset) => {
395                    let new_offset = (i as i32 + offset) as usize;
396                    module.add_west_neighbour(new_offset);
397                }
398            }
399            modules.push(module);
400        }
401
402        Self {
403            w,
404            h,
405            draw_scale,
406            atlas,
407            tile_width: 32,
408            tile_height: 32,
409            tiles,
410            modules,
411            texture,
412            map_data: vec![0; w*h],
413            cell_tree_data: vec![TreeType::None; w*h],
414            corner_tree_data: vec![TreeType::None; (w+1)*(h+1)]
415        }
416    }
Source

pub fn add_north_neighbour(&mut self, idx: usize)

A function which adds a neighbour on a north side

Examples found in repository?
examples/wang_corner_carpet.rs (line 121)
69    pub async fn new(w: usize, h: usize) -> Self {
70        let InternalGlContext {
71            quad_context: ctx, ..
72        } = unsafe { get_internal_gl() };
73
74        let texture_bytes = load_file("assets/wang_4_corner.png").await.unwrap();
75
76        let img = image::load_from_memory(&texture_bytes[..])
77            .unwrap_or_else(|e| panic!("{}", e))
78            .to_rgba8();
79
80        let img_w = img.width();
81        let img_h = img.height();
82
83        let texture = Texture2D::from_miniquad_texture(
84            miniquad::Texture::from_data_and_format(
85                ctx,
86                &img.into_raw(),
87                TextureParams {
88                    format: TextureFormat::RGBA8,
89                    wrap: TextureWrap::Clamp,
90                    filter: FilterMode::Nearest,
91                    width: img_w,
92                    height: img_h
93                }
94            )
95        );
96
97        let tiles = (0..=255)
98            .map(|idx| {
99                let width = 32;
100                let height = 32;
101                (
102                    idx as u8,
103                    SubRect {
104                        x: (idx % 16) * width,
105                        y: (idx / 16) * height,
106                        width,
107                        height
108                    }
109                )
110            })
111            .collect::<Vec<_>>();
112
113        let modules = tiles
114            .iter()
115            .map(|tile| {
116                let mut module: WfcModule<CustomBitSet> = WfcModule::new();
117                for i in 0..tiles.len() {
118                    let other_tile = &tiles[i];
119                    if get_north_west(tile.0) == get_south_west(other_tile.0) &&
120                        get_north_east(tile.0) == get_south_east(other_tile.0) {
121                        module.add_north_neighbour(i);
122                    }
123                    if get_south_west(tile.0) == get_north_west(other_tile.0) &&
124                        get_south_east(tile.0) == get_north_east(other_tile.0) {
125                        module.add_south_neighbour(i);
126                    }
127                    if get_north_west(tile.0) == get_north_east(other_tile.0) &&
128                        get_south_west(tile.0) == get_south_east(other_tile.0) {
129                        module.add_west_neighbour(i);
130                    }
131                    if get_north_east(tile.0) == get_north_west(other_tile.0) &&
132                        get_south_east(tile.0) == get_south_west(other_tile.0) {
133                        module.add_east_neighbour(i);
134                    }
135                }
136                module
137            })
138            .collect::<Vec<_>>();
139
140        Self {
141            w,
142            h,
143            tile_width: 32,
144            tile_height: 32,
145            tiles,
146            modules,
147            texture,
148            map_data: vec![0; w*h]
149        }
150    }
More examples
Hide additional examples
examples/dungeon.rs (line 321)
144    pub async fn new(w: usize, h: usize) -> Self {
145        let InternalGlContext {
146            quad_context: ctx, ..
147        } = unsafe { get_internal_gl() };
148
149        let dungeon_bytes = load_file("assets/dungeon_tiles.png").await.unwrap();
150
151        let img = image::load_from_memory(&dungeon_bytes[..])
152            .unwrap_or_else(|e| panic!("{}", e))
153            .to_rgba8();
154
155        let img_w = img.width();
156        let img_h = img.height();
157
158        let texture = Texture2D::from_miniquad_texture(
159            miniquad::Texture::from_data_and_format(
160                ctx,
161                &img.into_raw(),
162                TextureParams {
163                    format: TextureFormat::RGBA8,
164                    wrap: TextureWrap::Clamp,
165                    filter: FilterMode::Nearest,
166                    width: img_w,
167                    height: img_h
168                }
169            )
170        );
171
172        let tiles_bytes = load_file("assets/dungeon_tiles.ron").await.unwrap();
173        let dungeon_tiles: DungeonTiles = from_reader(&tiles_bytes[..]).unwrap();
174
175        let mut tiles = Vec::new();
176        for (kind_code, subrects) in dungeon_tiles.wang_4_corner_tiles.iter() {
177            tiles.push(Tile {
178                kind: TileKind::Wang4Corner(*kind_code),
179                subrects: subrects.clone(),
180                neighbours_east: Vec::new(),
181                neighbours_west: Vec::new(),
182                neighbours_north: Vec::new(),
183                neighbours_south: Vec::new()
184            });
185        }
186        // We need to be sure that zero tile is always a "void" tile, so we doing an extra sort step
187        tiles.sort_by(|lhs, rhs| {
188            match (lhs.kind, rhs.kind) {
189                (TileKind::Wang4Corner(kind_lhs), TileKind::Wang4Corner(kind_rhs)) => kind_lhs.cmp(&kind_rhs),
190                _ => Ordering::Equal
191            }
192        });
193
194        for i in 0..tiles.len() {
195            let current_kind = tiles[i].kind;
196            for j in 0..tiles.len() {
197                let candidate_kind = tiles[j].kind;
198                let (matches_north, matches_south, matches_east, matches_west) = {
199                    match (current_kind, candidate_kind) {
200                        (TileKind::Wang4Corner(current), TileKind::Wang4Corner(candidate)) => {
201                            (
202                                get_north_east(current) == get_south_east(candidate) &&
203                                    get_north_west(current) == get_south_west(candidate),
204
205                                get_south_east(current) == get_north_east(candidate) &&
206                                    get_south_west(current) == get_north_west(candidate),
207
208                                get_north_east(current) == get_north_west(candidate) &&
209                                    get_south_east(current) == get_south_west(candidate),
210
211                                get_north_west(current) == get_north_east(candidate) &&
212                                    get_south_west(current) == get_south_east(candidate),
213                            )
214                        },
215                        _ => continue
216                    }
217                };
218                if matches_east {
219                    tiles[i].neighbours_east.push(candidate_kind);
220                }
221                if matches_west {
222                    tiles[i].neighbours_west.push(candidate_kind);
223                }
224                if matches_north {
225                    tiles[i].neighbours_north.push(candidate_kind);
226                }
227                if matches_south {
228                    tiles[i].neighbours_south.push(candidate_kind);
229                }
230            }
231        }
232
233        //Add bridges:
234        {
235            let bridge_tiles_offset = tiles.len();
236            tiles.extend_from_slice(&dungeon_tiles.extra_tiles[..]);
237
238            let mut bridge_match_queue_south = VecDeque::new();
239            let mut bridge_match_queue_north = VecDeque::new();
240            let mut bridge_match_queue_east = VecDeque::new();
241            let mut bridge_match_queue_west = VecDeque::new();
242
243            for bridge_tile in &tiles[bridge_tiles_offset..] {
244                for south_neighbour in bridge_tile.neighbours_south.iter() {
245                    if let TileKind::Wang4Corner(kind) = south_neighbour {
246                        for i in 0..bridge_tiles_offset {
247                            match tiles[i].kind {
248                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
249                                    bridge_match_queue_south.push_back((bridge_tile.kind, i))
250                                },
251                                _ => ()
252                            };
253                        }
254                    }
255                }
256                for north_neighbour in bridge_tile.neighbours_north.iter() {
257                    if let TileKind::Wang4Corner(kind) = north_neighbour {
258                        for i in 0..bridge_tiles_offset {
259                            match tiles[i].kind {
260                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
261                                    bridge_match_queue_north.push_back((bridge_tile.kind, i))
262                                },
263                                _ => ()
264                            };
265                        }
266                    }
267                }
268                for east_neighbour in bridge_tile.neighbours_east.iter() {
269                    if let TileKind::Wang4Corner(kind) = east_neighbour {
270                        for i in 0..bridge_tiles_offset {
271                            match tiles[i].kind {
272                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
273                                    bridge_match_queue_east.push_back((bridge_tile.kind, i))
274                                },
275                                _ => ()
276                            };
277                        }
278                    }
279                }
280                for west_neighbour in bridge_tile.neighbours_west.iter() {
281                    if let TileKind::Wang4Corner(kind) = west_neighbour {
282                        for i in 0..bridge_tiles_offset {
283                            match tiles[i].kind {
284                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
285                                    bridge_match_queue_west.push_back((bridge_tile.kind, i))
286                                },
287                                _ => ()
288                            };
289                        }
290                    }
291                }
292            }
293
294            while !bridge_match_queue_south.is_empty() {
295                let next_match = bridge_match_queue_south.pop_front().unwrap();
296                tiles[next_match.1].neighbours_north.push(next_match.0);
297            }
298
299            while !bridge_match_queue_north.is_empty() {
300                let next_match = bridge_match_queue_north.pop_front().unwrap();
301                tiles[next_match.1].neighbours_south.push(next_match.0);
302            }
303
304            while !bridge_match_queue_east.is_empty() {
305                let next_match = bridge_match_queue_east.pop_front().unwrap();
306                tiles[next_match.1].neighbours_west.push(next_match.0);
307            }
308
309            while !bridge_match_queue_west.is_empty() {
310                let next_match = bridge_match_queue_west.pop_front().unwrap();
311                tiles[next_match.1].neighbours_east.push(next_match.0);
312            }
313        }
314
315        let modules = tiles
316            .iter()
317            .map(|tile| {
318                let mut module: WfcModule<CustomBitSet> = WfcModule::new();
319                for i in 0..tiles.len() {
320                    if tile.neighbours_north.contains(&tiles[i].kind) {
321                        module.add_north_neighbour(i);
322                    }
323                    if tile.neighbours_south.contains(&tiles[i].kind) {
324                        module.add_south_neighbour(i);
325                    }
326                    if tile.neighbours_west.contains(&tiles[i].kind) {
327                        module.add_west_neighbour(i);
328                    }
329                    if tile.neighbours_east.contains(&tiles[i].kind) {
330                        module.add_east_neighbour(i);
331                    }
332                }
333                module
334            })
335            .collect::<Vec<_>>();
336        
337        Self {
338            w,
339            h,
340            tile_width: dungeon_tiles.tile_width,
341            tile_height: dungeon_tiles.tile_height,
342            tiles,
343            modules,
344            texture,
345            map_data: vec![(0, 0); w*h]
346        }
347    }
examples/summer_garden.rs (line 339)
183    pub async fn new(w: usize, h: usize, draw_scale: f32) -> Self {
184        let InternalGlContext {
185            quad_context: ctx, ..
186        } = unsafe { get_internal_gl() };
187
188        let texture_bytes = load_file("assets/reduced_wang_scheme.png").await.unwrap();
189
190        let img = image::load_from_memory(&texture_bytes[..])
191            .unwrap_or_else(|e| panic!("{}", e))
192            .to_rgba8();
193
194        let img_w = img.width();
195        let img_h = img.height();
196
197        let texture = Texture2D::from_miniquad_texture(
198            miniquad::Texture::from_data_and_format(
199                ctx,
200                &img.into_raw(),
201                TextureParams {
202                    format: TextureFormat::RGBA8,
203                    wrap: TextureWrap::Clamp,
204                    filter: FilterMode::Nearest,
205                    width: img_w,
206                    height: img_h
207                }
208            )
209        );
210
211        let atlas_bytes = load_file("assets/reduced_wang_scheme.ron").await.unwrap();
212        let atlas: SummerGardenAtlas = from_reader(&atlas_bytes[..]).unwrap();
213
214        let mut tile_sides = Vec::new();
215        let mut neighbour_strategies = Vec::new();
216        let mut tiles = Vec::new();
217
218        {
219            for tile_cfg in atlas.terrain_tile_configs.iter() {
220                for pattern in &[
221                    &atlas.reduced_wang_patterns[..],
222                    &atlas.extended_set_1_patterns_north_west[..],
223                    &atlas.extended_set_1_patterns_north_east[..],
224                    &atlas.extended_set_1_patterns_south_west[..],
225                    &atlas.extended_set_1_patterns_south_east[..],
226                    &atlas.extended_set_2_patterns_north_west[..],
227                    &atlas.extended_set_2_patterns_north_east[..],
228                    &atlas.extended_set_2_patterns_south_west[..],
229                    &atlas.extended_set_2_patterns_south_east[..],
230                ] {
231                    tile_sides.extend(
232                        pattern.iter().map(
233                            |pattern| {
234                                TileSides {
235                                    north_west: match pattern.north_west {
236                                        TileKind::Inner => { tile_cfg.inner_type }
237                                        TileKind::Outer => { tile_cfg.outer_type }
238                                    },
239                                    north_east: match pattern.north_east {
240                                        TileKind::Inner => { tile_cfg.inner_type }
241                                        TileKind::Outer => { tile_cfg.outer_type }
242                                    },
243                                    south_west: match pattern.south_west {
244                                        TileKind::Inner => { tile_cfg.inner_type }
245                                        TileKind::Outer => { tile_cfg.outer_type }
246                                    },
247                                    south_east: match pattern.south_east {
248                                        TileKind::Inner => { tile_cfg.inner_type }
249                                        TileKind::Outer => { tile_cfg.outer_type }
250                                    }
251                                }
252                            }
253                        )
254                    );
255                }
256                for j in 0..4 {
257                    for i in 0..4 {
258                        tiles.push(SubRect{
259                            x: i * 32 + tile_cfg.x_offset,
260                            y: j * 32 + tile_cfg.y_offset,
261                            width: 32,
262                            height: 32
263                        })
264                    }
265                }
266                for jj in 0..2 {
267                    for ii in 0..2 {
268                        for j in 0..2 {
269                            for i in 0..2 {
270                                tiles.push(SubRect{
271                                    x: (i + ii * 2) * 32 + tile_cfg.x_offset + 256,
272                                    y: (j + jj * 2) * 32 + tile_cfg.y_offset,
273                                    width: 32,
274                                    height: 32
275                                })
276                            }
277                        }
278                    }
279                }
280                for jj in 0..2 {
281                    for ii in 0..2 {
282                        for j in 0..2 {
283                            for i in 0..2 {
284                                tiles.push(SubRect{
285                                    x: (i + ii * 2) * 32 + tile_cfg.x_offset,
286                                    y: (j + jj * 2) * 32 + tile_cfg.y_offset + 256,
287                                    width: 32,
288                                    height: 32
289                                })
290                            }
291                        }
292                    }
293                }
294                neighbour_strategies.extend_from_slice(&atlas.reduced_wang_neighbour_strategy[..]);
295                for _ in 0..8 {
296                    neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_2_x_2[..]);
297                }
298            }
299            tile_sides.extend_from_slice(&atlas.vertical_bridge_sides[..]);
300            tile_sides.extend_from_slice(&atlas.horizontal_bridge_sides[..]);
301            for j in 0..3 {
302                for i in 0..3 {
303                    tiles.push(SubRect{
304                        x: i * 32 + 256,
305                        y: j * 32 + 256,
306                        width: 32,
307                        height: 32
308                    })
309                }
310            }
311            for j in 0..3 {
312                for i in 0..3 {
313                    tiles.push(SubRect{
314                        x: i * 32 + 256 + 96,
315                        y: j * 32 + 256,
316                        width: 32,
317                        height: 32
318                    })
319                }
320            }
321            neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
322            neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
323
324            assert_eq!(tile_sides.len(), neighbour_strategies.len());
325        }
326
327        let mut modules = Vec::new();
328        for i in 0..tile_sides.len() {
329            let current_sides = tile_sides[i];
330            let mut module: WfcModule<CustomBitSet> = WfcModule::new();
331            match neighbour_strategies[i].north {
332                NeighbourKind::WangCorners => {
333                    for j in 0..tile_sides.len() {
334                        if neighbour_strategies[j].south != NeighbourKind::WangCorners {
335                            continue;
336                        }
337                        if tile_sides[j].south_west == current_sides.north_west &&
338                            tile_sides[j].south_east == current_sides.north_east {
339                            module.add_north_neighbour(j);
340                        }
341                    }
342                }
343                NeighbourKind::RelOffset(offset) => {
344                    let new_offset = (i as i32 + offset) as usize;
345                    module.add_north_neighbour(new_offset);
346                }
347            }
348            match neighbour_strategies[i].south {
349                NeighbourKind::WangCorners => {
350                    for j in 0..tile_sides.len() {
351                        if neighbour_strategies[j].north != NeighbourKind::WangCorners {
352                            continue;
353                        }
354                        if tile_sides[j].north_west == current_sides.south_west &&
355                            tile_sides[j].north_east == current_sides.south_east {
356                            module.add_south_neighbour(j);
357                        }
358                    }
359                }
360                NeighbourKind::RelOffset(offset) => {
361                    let new_offset = (i as i32 + offset) as usize;
362                    module.add_south_neighbour(new_offset);
363                }
364            }
365            match neighbour_strategies[i].east {
366                NeighbourKind::WangCorners => {
367                    for j in 0..tile_sides.len() {
368                        if neighbour_strategies[j].west != NeighbourKind::WangCorners {
369                            continue;
370                        }
371                        if tile_sides[j].north_west == current_sides.north_east &&
372                            tile_sides[j].south_west == current_sides.south_east {
373                            module.add_east_neighbour(j);
374                        }
375                    }
376                }
377                NeighbourKind::RelOffset(offset) => {
378                    let new_offset = (i as i32 + offset) as usize;
379                    module.add_east_neighbour(new_offset);
380                }
381            }
382            match neighbour_strategies[i].west {
383                NeighbourKind::WangCorners => {
384                    for j in 0..tile_sides.len() {
385                        if neighbour_strategies[j].east != NeighbourKind::WangCorners {
386                            continue;
387                        }
388                        if tile_sides[j].north_east == current_sides.north_west &&
389                            tile_sides[j].south_east == current_sides.south_west {
390                            module.add_west_neighbour(j);
391                        }
392                    }
393                }
394                NeighbourKind::RelOffset(offset) => {
395                    let new_offset = (i as i32 + offset) as usize;
396                    module.add_west_neighbour(new_offset);
397                }
398            }
399            modules.push(module);
400        }
401
402        Self {
403            w,
404            h,
405            draw_scale,
406            atlas,
407            tile_width: 32,
408            tile_height: 32,
409            tiles,
410            modules,
411            texture,
412            map_data: vec![0; w*h],
413            cell_tree_data: vec![TreeType::None; w*h],
414            corner_tree_data: vec![TreeType::None; (w+1)*(h+1)]
415        }
416    }
Source

pub fn add_south_neighbour(&mut self, idx: usize)

A function which adds a neighbour on a south side

Examples found in repository?
examples/wang_corner_carpet.rs (line 125)
69    pub async fn new(w: usize, h: usize) -> Self {
70        let InternalGlContext {
71            quad_context: ctx, ..
72        } = unsafe { get_internal_gl() };
73
74        let texture_bytes = load_file("assets/wang_4_corner.png").await.unwrap();
75
76        let img = image::load_from_memory(&texture_bytes[..])
77            .unwrap_or_else(|e| panic!("{}", e))
78            .to_rgba8();
79
80        let img_w = img.width();
81        let img_h = img.height();
82
83        let texture = Texture2D::from_miniquad_texture(
84            miniquad::Texture::from_data_and_format(
85                ctx,
86                &img.into_raw(),
87                TextureParams {
88                    format: TextureFormat::RGBA8,
89                    wrap: TextureWrap::Clamp,
90                    filter: FilterMode::Nearest,
91                    width: img_w,
92                    height: img_h
93                }
94            )
95        );
96
97        let tiles = (0..=255)
98            .map(|idx| {
99                let width = 32;
100                let height = 32;
101                (
102                    idx as u8,
103                    SubRect {
104                        x: (idx % 16) * width,
105                        y: (idx / 16) * height,
106                        width,
107                        height
108                    }
109                )
110            })
111            .collect::<Vec<_>>();
112
113        let modules = tiles
114            .iter()
115            .map(|tile| {
116                let mut module: WfcModule<CustomBitSet> = WfcModule::new();
117                for i in 0..tiles.len() {
118                    let other_tile = &tiles[i];
119                    if get_north_west(tile.0) == get_south_west(other_tile.0) &&
120                        get_north_east(tile.0) == get_south_east(other_tile.0) {
121                        module.add_north_neighbour(i);
122                    }
123                    if get_south_west(tile.0) == get_north_west(other_tile.0) &&
124                        get_south_east(tile.0) == get_north_east(other_tile.0) {
125                        module.add_south_neighbour(i);
126                    }
127                    if get_north_west(tile.0) == get_north_east(other_tile.0) &&
128                        get_south_west(tile.0) == get_south_east(other_tile.0) {
129                        module.add_west_neighbour(i);
130                    }
131                    if get_north_east(tile.0) == get_north_west(other_tile.0) &&
132                        get_south_east(tile.0) == get_south_west(other_tile.0) {
133                        module.add_east_neighbour(i);
134                    }
135                }
136                module
137            })
138            .collect::<Vec<_>>();
139
140        Self {
141            w,
142            h,
143            tile_width: 32,
144            tile_height: 32,
145            tiles,
146            modules,
147            texture,
148            map_data: vec![0; w*h]
149        }
150    }
More examples
Hide additional examples
examples/dungeon.rs (line 324)
144    pub async fn new(w: usize, h: usize) -> Self {
145        let InternalGlContext {
146            quad_context: ctx, ..
147        } = unsafe { get_internal_gl() };
148
149        let dungeon_bytes = load_file("assets/dungeon_tiles.png").await.unwrap();
150
151        let img = image::load_from_memory(&dungeon_bytes[..])
152            .unwrap_or_else(|e| panic!("{}", e))
153            .to_rgba8();
154
155        let img_w = img.width();
156        let img_h = img.height();
157
158        let texture = Texture2D::from_miniquad_texture(
159            miniquad::Texture::from_data_and_format(
160                ctx,
161                &img.into_raw(),
162                TextureParams {
163                    format: TextureFormat::RGBA8,
164                    wrap: TextureWrap::Clamp,
165                    filter: FilterMode::Nearest,
166                    width: img_w,
167                    height: img_h
168                }
169            )
170        );
171
172        let tiles_bytes = load_file("assets/dungeon_tiles.ron").await.unwrap();
173        let dungeon_tiles: DungeonTiles = from_reader(&tiles_bytes[..]).unwrap();
174
175        let mut tiles = Vec::new();
176        for (kind_code, subrects) in dungeon_tiles.wang_4_corner_tiles.iter() {
177            tiles.push(Tile {
178                kind: TileKind::Wang4Corner(*kind_code),
179                subrects: subrects.clone(),
180                neighbours_east: Vec::new(),
181                neighbours_west: Vec::new(),
182                neighbours_north: Vec::new(),
183                neighbours_south: Vec::new()
184            });
185        }
186        // We need to be sure that zero tile is always a "void" tile, so we doing an extra sort step
187        tiles.sort_by(|lhs, rhs| {
188            match (lhs.kind, rhs.kind) {
189                (TileKind::Wang4Corner(kind_lhs), TileKind::Wang4Corner(kind_rhs)) => kind_lhs.cmp(&kind_rhs),
190                _ => Ordering::Equal
191            }
192        });
193
194        for i in 0..tiles.len() {
195            let current_kind = tiles[i].kind;
196            for j in 0..tiles.len() {
197                let candidate_kind = tiles[j].kind;
198                let (matches_north, matches_south, matches_east, matches_west) = {
199                    match (current_kind, candidate_kind) {
200                        (TileKind::Wang4Corner(current), TileKind::Wang4Corner(candidate)) => {
201                            (
202                                get_north_east(current) == get_south_east(candidate) &&
203                                    get_north_west(current) == get_south_west(candidate),
204
205                                get_south_east(current) == get_north_east(candidate) &&
206                                    get_south_west(current) == get_north_west(candidate),
207
208                                get_north_east(current) == get_north_west(candidate) &&
209                                    get_south_east(current) == get_south_west(candidate),
210
211                                get_north_west(current) == get_north_east(candidate) &&
212                                    get_south_west(current) == get_south_east(candidate),
213                            )
214                        },
215                        _ => continue
216                    }
217                };
218                if matches_east {
219                    tiles[i].neighbours_east.push(candidate_kind);
220                }
221                if matches_west {
222                    tiles[i].neighbours_west.push(candidate_kind);
223                }
224                if matches_north {
225                    tiles[i].neighbours_north.push(candidate_kind);
226                }
227                if matches_south {
228                    tiles[i].neighbours_south.push(candidate_kind);
229                }
230            }
231        }
232
233        //Add bridges:
234        {
235            let bridge_tiles_offset = tiles.len();
236            tiles.extend_from_slice(&dungeon_tiles.extra_tiles[..]);
237
238            let mut bridge_match_queue_south = VecDeque::new();
239            let mut bridge_match_queue_north = VecDeque::new();
240            let mut bridge_match_queue_east = VecDeque::new();
241            let mut bridge_match_queue_west = VecDeque::new();
242
243            for bridge_tile in &tiles[bridge_tiles_offset..] {
244                for south_neighbour in bridge_tile.neighbours_south.iter() {
245                    if let TileKind::Wang4Corner(kind) = south_neighbour {
246                        for i in 0..bridge_tiles_offset {
247                            match tiles[i].kind {
248                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
249                                    bridge_match_queue_south.push_back((bridge_tile.kind, i))
250                                },
251                                _ => ()
252                            };
253                        }
254                    }
255                }
256                for north_neighbour in bridge_tile.neighbours_north.iter() {
257                    if let TileKind::Wang4Corner(kind) = north_neighbour {
258                        for i in 0..bridge_tiles_offset {
259                            match tiles[i].kind {
260                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
261                                    bridge_match_queue_north.push_back((bridge_tile.kind, i))
262                                },
263                                _ => ()
264                            };
265                        }
266                    }
267                }
268                for east_neighbour in bridge_tile.neighbours_east.iter() {
269                    if let TileKind::Wang4Corner(kind) = east_neighbour {
270                        for i in 0..bridge_tiles_offset {
271                            match tiles[i].kind {
272                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
273                                    bridge_match_queue_east.push_back((bridge_tile.kind, i))
274                                },
275                                _ => ()
276                            };
277                        }
278                    }
279                }
280                for west_neighbour in bridge_tile.neighbours_west.iter() {
281                    if let TileKind::Wang4Corner(kind) = west_neighbour {
282                        for i in 0..bridge_tiles_offset {
283                            match tiles[i].kind {
284                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
285                                    bridge_match_queue_west.push_back((bridge_tile.kind, i))
286                                },
287                                _ => ()
288                            };
289                        }
290                    }
291                }
292            }
293
294            while !bridge_match_queue_south.is_empty() {
295                let next_match = bridge_match_queue_south.pop_front().unwrap();
296                tiles[next_match.1].neighbours_north.push(next_match.0);
297            }
298
299            while !bridge_match_queue_north.is_empty() {
300                let next_match = bridge_match_queue_north.pop_front().unwrap();
301                tiles[next_match.1].neighbours_south.push(next_match.0);
302            }
303
304            while !bridge_match_queue_east.is_empty() {
305                let next_match = bridge_match_queue_east.pop_front().unwrap();
306                tiles[next_match.1].neighbours_west.push(next_match.0);
307            }
308
309            while !bridge_match_queue_west.is_empty() {
310                let next_match = bridge_match_queue_west.pop_front().unwrap();
311                tiles[next_match.1].neighbours_east.push(next_match.0);
312            }
313        }
314
315        let modules = tiles
316            .iter()
317            .map(|tile| {
318                let mut module: WfcModule<CustomBitSet> = WfcModule::new();
319                for i in 0..tiles.len() {
320                    if tile.neighbours_north.contains(&tiles[i].kind) {
321                        module.add_north_neighbour(i);
322                    }
323                    if tile.neighbours_south.contains(&tiles[i].kind) {
324                        module.add_south_neighbour(i);
325                    }
326                    if tile.neighbours_west.contains(&tiles[i].kind) {
327                        module.add_west_neighbour(i);
328                    }
329                    if tile.neighbours_east.contains(&tiles[i].kind) {
330                        module.add_east_neighbour(i);
331                    }
332                }
333                module
334            })
335            .collect::<Vec<_>>();
336        
337        Self {
338            w,
339            h,
340            tile_width: dungeon_tiles.tile_width,
341            tile_height: dungeon_tiles.tile_height,
342            tiles,
343            modules,
344            texture,
345            map_data: vec![(0, 0); w*h]
346        }
347    }
examples/summer_garden.rs (line 356)
183    pub async fn new(w: usize, h: usize, draw_scale: f32) -> Self {
184        let InternalGlContext {
185            quad_context: ctx, ..
186        } = unsafe { get_internal_gl() };
187
188        let texture_bytes = load_file("assets/reduced_wang_scheme.png").await.unwrap();
189
190        let img = image::load_from_memory(&texture_bytes[..])
191            .unwrap_or_else(|e| panic!("{}", e))
192            .to_rgba8();
193
194        let img_w = img.width();
195        let img_h = img.height();
196
197        let texture = Texture2D::from_miniquad_texture(
198            miniquad::Texture::from_data_and_format(
199                ctx,
200                &img.into_raw(),
201                TextureParams {
202                    format: TextureFormat::RGBA8,
203                    wrap: TextureWrap::Clamp,
204                    filter: FilterMode::Nearest,
205                    width: img_w,
206                    height: img_h
207                }
208            )
209        );
210
211        let atlas_bytes = load_file("assets/reduced_wang_scheme.ron").await.unwrap();
212        let atlas: SummerGardenAtlas = from_reader(&atlas_bytes[..]).unwrap();
213
214        let mut tile_sides = Vec::new();
215        let mut neighbour_strategies = Vec::new();
216        let mut tiles = Vec::new();
217
218        {
219            for tile_cfg in atlas.terrain_tile_configs.iter() {
220                for pattern in &[
221                    &atlas.reduced_wang_patterns[..],
222                    &atlas.extended_set_1_patterns_north_west[..],
223                    &atlas.extended_set_1_patterns_north_east[..],
224                    &atlas.extended_set_1_patterns_south_west[..],
225                    &atlas.extended_set_1_patterns_south_east[..],
226                    &atlas.extended_set_2_patterns_north_west[..],
227                    &atlas.extended_set_2_patterns_north_east[..],
228                    &atlas.extended_set_2_patterns_south_west[..],
229                    &atlas.extended_set_2_patterns_south_east[..],
230                ] {
231                    tile_sides.extend(
232                        pattern.iter().map(
233                            |pattern| {
234                                TileSides {
235                                    north_west: match pattern.north_west {
236                                        TileKind::Inner => { tile_cfg.inner_type }
237                                        TileKind::Outer => { tile_cfg.outer_type }
238                                    },
239                                    north_east: match pattern.north_east {
240                                        TileKind::Inner => { tile_cfg.inner_type }
241                                        TileKind::Outer => { tile_cfg.outer_type }
242                                    },
243                                    south_west: match pattern.south_west {
244                                        TileKind::Inner => { tile_cfg.inner_type }
245                                        TileKind::Outer => { tile_cfg.outer_type }
246                                    },
247                                    south_east: match pattern.south_east {
248                                        TileKind::Inner => { tile_cfg.inner_type }
249                                        TileKind::Outer => { tile_cfg.outer_type }
250                                    }
251                                }
252                            }
253                        )
254                    );
255                }
256                for j in 0..4 {
257                    for i in 0..4 {
258                        tiles.push(SubRect{
259                            x: i * 32 + tile_cfg.x_offset,
260                            y: j * 32 + tile_cfg.y_offset,
261                            width: 32,
262                            height: 32
263                        })
264                    }
265                }
266                for jj in 0..2 {
267                    for ii in 0..2 {
268                        for j in 0..2 {
269                            for i in 0..2 {
270                                tiles.push(SubRect{
271                                    x: (i + ii * 2) * 32 + tile_cfg.x_offset + 256,
272                                    y: (j + jj * 2) * 32 + tile_cfg.y_offset,
273                                    width: 32,
274                                    height: 32
275                                })
276                            }
277                        }
278                    }
279                }
280                for jj in 0..2 {
281                    for ii in 0..2 {
282                        for j in 0..2 {
283                            for i in 0..2 {
284                                tiles.push(SubRect{
285                                    x: (i + ii * 2) * 32 + tile_cfg.x_offset,
286                                    y: (j + jj * 2) * 32 + tile_cfg.y_offset + 256,
287                                    width: 32,
288                                    height: 32
289                                })
290                            }
291                        }
292                    }
293                }
294                neighbour_strategies.extend_from_slice(&atlas.reduced_wang_neighbour_strategy[..]);
295                for _ in 0..8 {
296                    neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_2_x_2[..]);
297                }
298            }
299            tile_sides.extend_from_slice(&atlas.vertical_bridge_sides[..]);
300            tile_sides.extend_from_slice(&atlas.horizontal_bridge_sides[..]);
301            for j in 0..3 {
302                for i in 0..3 {
303                    tiles.push(SubRect{
304                        x: i * 32 + 256,
305                        y: j * 32 + 256,
306                        width: 32,
307                        height: 32
308                    })
309                }
310            }
311            for j in 0..3 {
312                for i in 0..3 {
313                    tiles.push(SubRect{
314                        x: i * 32 + 256 + 96,
315                        y: j * 32 + 256,
316                        width: 32,
317                        height: 32
318                    })
319                }
320            }
321            neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
322            neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
323
324            assert_eq!(tile_sides.len(), neighbour_strategies.len());
325        }
326
327        let mut modules = Vec::new();
328        for i in 0..tile_sides.len() {
329            let current_sides = tile_sides[i];
330            let mut module: WfcModule<CustomBitSet> = WfcModule::new();
331            match neighbour_strategies[i].north {
332                NeighbourKind::WangCorners => {
333                    for j in 0..tile_sides.len() {
334                        if neighbour_strategies[j].south != NeighbourKind::WangCorners {
335                            continue;
336                        }
337                        if tile_sides[j].south_west == current_sides.north_west &&
338                            tile_sides[j].south_east == current_sides.north_east {
339                            module.add_north_neighbour(j);
340                        }
341                    }
342                }
343                NeighbourKind::RelOffset(offset) => {
344                    let new_offset = (i as i32 + offset) as usize;
345                    module.add_north_neighbour(new_offset);
346                }
347            }
348            match neighbour_strategies[i].south {
349                NeighbourKind::WangCorners => {
350                    for j in 0..tile_sides.len() {
351                        if neighbour_strategies[j].north != NeighbourKind::WangCorners {
352                            continue;
353                        }
354                        if tile_sides[j].north_west == current_sides.south_west &&
355                            tile_sides[j].north_east == current_sides.south_east {
356                            module.add_south_neighbour(j);
357                        }
358                    }
359                }
360                NeighbourKind::RelOffset(offset) => {
361                    let new_offset = (i as i32 + offset) as usize;
362                    module.add_south_neighbour(new_offset);
363                }
364            }
365            match neighbour_strategies[i].east {
366                NeighbourKind::WangCorners => {
367                    for j in 0..tile_sides.len() {
368                        if neighbour_strategies[j].west != NeighbourKind::WangCorners {
369                            continue;
370                        }
371                        if tile_sides[j].north_west == current_sides.north_east &&
372                            tile_sides[j].south_west == current_sides.south_east {
373                            module.add_east_neighbour(j);
374                        }
375                    }
376                }
377                NeighbourKind::RelOffset(offset) => {
378                    let new_offset = (i as i32 + offset) as usize;
379                    module.add_east_neighbour(new_offset);
380                }
381            }
382            match neighbour_strategies[i].west {
383                NeighbourKind::WangCorners => {
384                    for j in 0..tile_sides.len() {
385                        if neighbour_strategies[j].east != NeighbourKind::WangCorners {
386                            continue;
387                        }
388                        if tile_sides[j].north_east == current_sides.north_west &&
389                            tile_sides[j].south_east == current_sides.south_west {
390                            module.add_west_neighbour(j);
391                        }
392                    }
393                }
394                NeighbourKind::RelOffset(offset) => {
395                    let new_offset = (i as i32 + offset) as usize;
396                    module.add_west_neighbour(new_offset);
397                }
398            }
399            modules.push(module);
400        }
401
402        Self {
403            w,
404            h,
405            draw_scale,
406            atlas,
407            tile_width: 32,
408            tile_height: 32,
409            tiles,
410            modules,
411            texture,
412            map_data: vec![0; w*h],
413            cell_tree_data: vec![TreeType::None; w*h],
414            corner_tree_data: vec![TreeType::None; (w+1)*(h+1)]
415        }
416    }
Source

pub fn add_east_neighbour(&mut self, idx: usize)

A function which adds a neighbour on an east side

Examples found in repository?
examples/wang_corner_carpet.rs (line 133)
69    pub async fn new(w: usize, h: usize) -> Self {
70        let InternalGlContext {
71            quad_context: ctx, ..
72        } = unsafe { get_internal_gl() };
73
74        let texture_bytes = load_file("assets/wang_4_corner.png").await.unwrap();
75
76        let img = image::load_from_memory(&texture_bytes[..])
77            .unwrap_or_else(|e| panic!("{}", e))
78            .to_rgba8();
79
80        let img_w = img.width();
81        let img_h = img.height();
82
83        let texture = Texture2D::from_miniquad_texture(
84            miniquad::Texture::from_data_and_format(
85                ctx,
86                &img.into_raw(),
87                TextureParams {
88                    format: TextureFormat::RGBA8,
89                    wrap: TextureWrap::Clamp,
90                    filter: FilterMode::Nearest,
91                    width: img_w,
92                    height: img_h
93                }
94            )
95        );
96
97        let tiles = (0..=255)
98            .map(|idx| {
99                let width = 32;
100                let height = 32;
101                (
102                    idx as u8,
103                    SubRect {
104                        x: (idx % 16) * width,
105                        y: (idx / 16) * height,
106                        width,
107                        height
108                    }
109                )
110            })
111            .collect::<Vec<_>>();
112
113        let modules = tiles
114            .iter()
115            .map(|tile| {
116                let mut module: WfcModule<CustomBitSet> = WfcModule::new();
117                for i in 0..tiles.len() {
118                    let other_tile = &tiles[i];
119                    if get_north_west(tile.0) == get_south_west(other_tile.0) &&
120                        get_north_east(tile.0) == get_south_east(other_tile.0) {
121                        module.add_north_neighbour(i);
122                    }
123                    if get_south_west(tile.0) == get_north_west(other_tile.0) &&
124                        get_south_east(tile.0) == get_north_east(other_tile.0) {
125                        module.add_south_neighbour(i);
126                    }
127                    if get_north_west(tile.0) == get_north_east(other_tile.0) &&
128                        get_south_west(tile.0) == get_south_east(other_tile.0) {
129                        module.add_west_neighbour(i);
130                    }
131                    if get_north_east(tile.0) == get_north_west(other_tile.0) &&
132                        get_south_east(tile.0) == get_south_west(other_tile.0) {
133                        module.add_east_neighbour(i);
134                    }
135                }
136                module
137            })
138            .collect::<Vec<_>>();
139
140        Self {
141            w,
142            h,
143            tile_width: 32,
144            tile_height: 32,
145            tiles,
146            modules,
147            texture,
148            map_data: vec![0; w*h]
149        }
150    }
More examples
Hide additional examples
examples/dungeon.rs (line 330)
144    pub async fn new(w: usize, h: usize) -> Self {
145        let InternalGlContext {
146            quad_context: ctx, ..
147        } = unsafe { get_internal_gl() };
148
149        let dungeon_bytes = load_file("assets/dungeon_tiles.png").await.unwrap();
150
151        let img = image::load_from_memory(&dungeon_bytes[..])
152            .unwrap_or_else(|e| panic!("{}", e))
153            .to_rgba8();
154
155        let img_w = img.width();
156        let img_h = img.height();
157
158        let texture = Texture2D::from_miniquad_texture(
159            miniquad::Texture::from_data_and_format(
160                ctx,
161                &img.into_raw(),
162                TextureParams {
163                    format: TextureFormat::RGBA8,
164                    wrap: TextureWrap::Clamp,
165                    filter: FilterMode::Nearest,
166                    width: img_w,
167                    height: img_h
168                }
169            )
170        );
171
172        let tiles_bytes = load_file("assets/dungeon_tiles.ron").await.unwrap();
173        let dungeon_tiles: DungeonTiles = from_reader(&tiles_bytes[..]).unwrap();
174
175        let mut tiles = Vec::new();
176        for (kind_code, subrects) in dungeon_tiles.wang_4_corner_tiles.iter() {
177            tiles.push(Tile {
178                kind: TileKind::Wang4Corner(*kind_code),
179                subrects: subrects.clone(),
180                neighbours_east: Vec::new(),
181                neighbours_west: Vec::new(),
182                neighbours_north: Vec::new(),
183                neighbours_south: Vec::new()
184            });
185        }
186        // We need to be sure that zero tile is always a "void" tile, so we doing an extra sort step
187        tiles.sort_by(|lhs, rhs| {
188            match (lhs.kind, rhs.kind) {
189                (TileKind::Wang4Corner(kind_lhs), TileKind::Wang4Corner(kind_rhs)) => kind_lhs.cmp(&kind_rhs),
190                _ => Ordering::Equal
191            }
192        });
193
194        for i in 0..tiles.len() {
195            let current_kind = tiles[i].kind;
196            for j in 0..tiles.len() {
197                let candidate_kind = tiles[j].kind;
198                let (matches_north, matches_south, matches_east, matches_west) = {
199                    match (current_kind, candidate_kind) {
200                        (TileKind::Wang4Corner(current), TileKind::Wang4Corner(candidate)) => {
201                            (
202                                get_north_east(current) == get_south_east(candidate) &&
203                                    get_north_west(current) == get_south_west(candidate),
204
205                                get_south_east(current) == get_north_east(candidate) &&
206                                    get_south_west(current) == get_north_west(candidate),
207
208                                get_north_east(current) == get_north_west(candidate) &&
209                                    get_south_east(current) == get_south_west(candidate),
210
211                                get_north_west(current) == get_north_east(candidate) &&
212                                    get_south_west(current) == get_south_east(candidate),
213                            )
214                        },
215                        _ => continue
216                    }
217                };
218                if matches_east {
219                    tiles[i].neighbours_east.push(candidate_kind);
220                }
221                if matches_west {
222                    tiles[i].neighbours_west.push(candidate_kind);
223                }
224                if matches_north {
225                    tiles[i].neighbours_north.push(candidate_kind);
226                }
227                if matches_south {
228                    tiles[i].neighbours_south.push(candidate_kind);
229                }
230            }
231        }
232
233        //Add bridges:
234        {
235            let bridge_tiles_offset = tiles.len();
236            tiles.extend_from_slice(&dungeon_tiles.extra_tiles[..]);
237
238            let mut bridge_match_queue_south = VecDeque::new();
239            let mut bridge_match_queue_north = VecDeque::new();
240            let mut bridge_match_queue_east = VecDeque::new();
241            let mut bridge_match_queue_west = VecDeque::new();
242
243            for bridge_tile in &tiles[bridge_tiles_offset..] {
244                for south_neighbour in bridge_tile.neighbours_south.iter() {
245                    if let TileKind::Wang4Corner(kind) = south_neighbour {
246                        for i in 0..bridge_tiles_offset {
247                            match tiles[i].kind {
248                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
249                                    bridge_match_queue_south.push_back((bridge_tile.kind, i))
250                                },
251                                _ => ()
252                            };
253                        }
254                    }
255                }
256                for north_neighbour in bridge_tile.neighbours_north.iter() {
257                    if let TileKind::Wang4Corner(kind) = north_neighbour {
258                        for i in 0..bridge_tiles_offset {
259                            match tiles[i].kind {
260                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
261                                    bridge_match_queue_north.push_back((bridge_tile.kind, i))
262                                },
263                                _ => ()
264                            };
265                        }
266                    }
267                }
268                for east_neighbour in bridge_tile.neighbours_east.iter() {
269                    if let TileKind::Wang4Corner(kind) = east_neighbour {
270                        for i in 0..bridge_tiles_offset {
271                            match tiles[i].kind {
272                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
273                                    bridge_match_queue_east.push_back((bridge_tile.kind, i))
274                                },
275                                _ => ()
276                            };
277                        }
278                    }
279                }
280                for west_neighbour in bridge_tile.neighbours_west.iter() {
281                    if let TileKind::Wang4Corner(kind) = west_neighbour {
282                        for i in 0..bridge_tiles_offset {
283                            match tiles[i].kind {
284                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
285                                    bridge_match_queue_west.push_back((bridge_tile.kind, i))
286                                },
287                                _ => ()
288                            };
289                        }
290                    }
291                }
292            }
293
294            while !bridge_match_queue_south.is_empty() {
295                let next_match = bridge_match_queue_south.pop_front().unwrap();
296                tiles[next_match.1].neighbours_north.push(next_match.0);
297            }
298
299            while !bridge_match_queue_north.is_empty() {
300                let next_match = bridge_match_queue_north.pop_front().unwrap();
301                tiles[next_match.1].neighbours_south.push(next_match.0);
302            }
303
304            while !bridge_match_queue_east.is_empty() {
305                let next_match = bridge_match_queue_east.pop_front().unwrap();
306                tiles[next_match.1].neighbours_west.push(next_match.0);
307            }
308
309            while !bridge_match_queue_west.is_empty() {
310                let next_match = bridge_match_queue_west.pop_front().unwrap();
311                tiles[next_match.1].neighbours_east.push(next_match.0);
312            }
313        }
314
315        let modules = tiles
316            .iter()
317            .map(|tile| {
318                let mut module: WfcModule<CustomBitSet> = WfcModule::new();
319                for i in 0..tiles.len() {
320                    if tile.neighbours_north.contains(&tiles[i].kind) {
321                        module.add_north_neighbour(i);
322                    }
323                    if tile.neighbours_south.contains(&tiles[i].kind) {
324                        module.add_south_neighbour(i);
325                    }
326                    if tile.neighbours_west.contains(&tiles[i].kind) {
327                        module.add_west_neighbour(i);
328                    }
329                    if tile.neighbours_east.contains(&tiles[i].kind) {
330                        module.add_east_neighbour(i);
331                    }
332                }
333                module
334            })
335            .collect::<Vec<_>>();
336        
337        Self {
338            w,
339            h,
340            tile_width: dungeon_tiles.tile_width,
341            tile_height: dungeon_tiles.tile_height,
342            tiles,
343            modules,
344            texture,
345            map_data: vec![(0, 0); w*h]
346        }
347    }
examples/summer_garden.rs (line 373)
183    pub async fn new(w: usize, h: usize, draw_scale: f32) -> Self {
184        let InternalGlContext {
185            quad_context: ctx, ..
186        } = unsafe { get_internal_gl() };
187
188        let texture_bytes = load_file("assets/reduced_wang_scheme.png").await.unwrap();
189
190        let img = image::load_from_memory(&texture_bytes[..])
191            .unwrap_or_else(|e| panic!("{}", e))
192            .to_rgba8();
193
194        let img_w = img.width();
195        let img_h = img.height();
196
197        let texture = Texture2D::from_miniquad_texture(
198            miniquad::Texture::from_data_and_format(
199                ctx,
200                &img.into_raw(),
201                TextureParams {
202                    format: TextureFormat::RGBA8,
203                    wrap: TextureWrap::Clamp,
204                    filter: FilterMode::Nearest,
205                    width: img_w,
206                    height: img_h
207                }
208            )
209        );
210
211        let atlas_bytes = load_file("assets/reduced_wang_scheme.ron").await.unwrap();
212        let atlas: SummerGardenAtlas = from_reader(&atlas_bytes[..]).unwrap();
213
214        let mut tile_sides = Vec::new();
215        let mut neighbour_strategies = Vec::new();
216        let mut tiles = Vec::new();
217
218        {
219            for tile_cfg in atlas.terrain_tile_configs.iter() {
220                for pattern in &[
221                    &atlas.reduced_wang_patterns[..],
222                    &atlas.extended_set_1_patterns_north_west[..],
223                    &atlas.extended_set_1_patterns_north_east[..],
224                    &atlas.extended_set_1_patterns_south_west[..],
225                    &atlas.extended_set_1_patterns_south_east[..],
226                    &atlas.extended_set_2_patterns_north_west[..],
227                    &atlas.extended_set_2_patterns_north_east[..],
228                    &atlas.extended_set_2_patterns_south_west[..],
229                    &atlas.extended_set_2_patterns_south_east[..],
230                ] {
231                    tile_sides.extend(
232                        pattern.iter().map(
233                            |pattern| {
234                                TileSides {
235                                    north_west: match pattern.north_west {
236                                        TileKind::Inner => { tile_cfg.inner_type }
237                                        TileKind::Outer => { tile_cfg.outer_type }
238                                    },
239                                    north_east: match pattern.north_east {
240                                        TileKind::Inner => { tile_cfg.inner_type }
241                                        TileKind::Outer => { tile_cfg.outer_type }
242                                    },
243                                    south_west: match pattern.south_west {
244                                        TileKind::Inner => { tile_cfg.inner_type }
245                                        TileKind::Outer => { tile_cfg.outer_type }
246                                    },
247                                    south_east: match pattern.south_east {
248                                        TileKind::Inner => { tile_cfg.inner_type }
249                                        TileKind::Outer => { tile_cfg.outer_type }
250                                    }
251                                }
252                            }
253                        )
254                    );
255                }
256                for j in 0..4 {
257                    for i in 0..4 {
258                        tiles.push(SubRect{
259                            x: i * 32 + tile_cfg.x_offset,
260                            y: j * 32 + tile_cfg.y_offset,
261                            width: 32,
262                            height: 32
263                        })
264                    }
265                }
266                for jj in 0..2 {
267                    for ii in 0..2 {
268                        for j in 0..2 {
269                            for i in 0..2 {
270                                tiles.push(SubRect{
271                                    x: (i + ii * 2) * 32 + tile_cfg.x_offset + 256,
272                                    y: (j + jj * 2) * 32 + tile_cfg.y_offset,
273                                    width: 32,
274                                    height: 32
275                                })
276                            }
277                        }
278                    }
279                }
280                for jj in 0..2 {
281                    for ii in 0..2 {
282                        for j in 0..2 {
283                            for i in 0..2 {
284                                tiles.push(SubRect{
285                                    x: (i + ii * 2) * 32 + tile_cfg.x_offset,
286                                    y: (j + jj * 2) * 32 + tile_cfg.y_offset + 256,
287                                    width: 32,
288                                    height: 32
289                                })
290                            }
291                        }
292                    }
293                }
294                neighbour_strategies.extend_from_slice(&atlas.reduced_wang_neighbour_strategy[..]);
295                for _ in 0..8 {
296                    neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_2_x_2[..]);
297                }
298            }
299            tile_sides.extend_from_slice(&atlas.vertical_bridge_sides[..]);
300            tile_sides.extend_from_slice(&atlas.horizontal_bridge_sides[..]);
301            for j in 0..3 {
302                for i in 0..3 {
303                    tiles.push(SubRect{
304                        x: i * 32 + 256,
305                        y: j * 32 + 256,
306                        width: 32,
307                        height: 32
308                    })
309                }
310            }
311            for j in 0..3 {
312                for i in 0..3 {
313                    tiles.push(SubRect{
314                        x: i * 32 + 256 + 96,
315                        y: j * 32 + 256,
316                        width: 32,
317                        height: 32
318                    })
319                }
320            }
321            neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
322            neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
323
324            assert_eq!(tile_sides.len(), neighbour_strategies.len());
325        }
326
327        let mut modules = Vec::new();
328        for i in 0..tile_sides.len() {
329            let current_sides = tile_sides[i];
330            let mut module: WfcModule<CustomBitSet> = WfcModule::new();
331            match neighbour_strategies[i].north {
332                NeighbourKind::WangCorners => {
333                    for j in 0..tile_sides.len() {
334                        if neighbour_strategies[j].south != NeighbourKind::WangCorners {
335                            continue;
336                        }
337                        if tile_sides[j].south_west == current_sides.north_west &&
338                            tile_sides[j].south_east == current_sides.north_east {
339                            module.add_north_neighbour(j);
340                        }
341                    }
342                }
343                NeighbourKind::RelOffset(offset) => {
344                    let new_offset = (i as i32 + offset) as usize;
345                    module.add_north_neighbour(new_offset);
346                }
347            }
348            match neighbour_strategies[i].south {
349                NeighbourKind::WangCorners => {
350                    for j in 0..tile_sides.len() {
351                        if neighbour_strategies[j].north != NeighbourKind::WangCorners {
352                            continue;
353                        }
354                        if tile_sides[j].north_west == current_sides.south_west &&
355                            tile_sides[j].north_east == current_sides.south_east {
356                            module.add_south_neighbour(j);
357                        }
358                    }
359                }
360                NeighbourKind::RelOffset(offset) => {
361                    let new_offset = (i as i32 + offset) as usize;
362                    module.add_south_neighbour(new_offset);
363                }
364            }
365            match neighbour_strategies[i].east {
366                NeighbourKind::WangCorners => {
367                    for j in 0..tile_sides.len() {
368                        if neighbour_strategies[j].west != NeighbourKind::WangCorners {
369                            continue;
370                        }
371                        if tile_sides[j].north_west == current_sides.north_east &&
372                            tile_sides[j].south_west == current_sides.south_east {
373                            module.add_east_neighbour(j);
374                        }
375                    }
376                }
377                NeighbourKind::RelOffset(offset) => {
378                    let new_offset = (i as i32 + offset) as usize;
379                    module.add_east_neighbour(new_offset);
380                }
381            }
382            match neighbour_strategies[i].west {
383                NeighbourKind::WangCorners => {
384                    for j in 0..tile_sides.len() {
385                        if neighbour_strategies[j].east != NeighbourKind::WangCorners {
386                            continue;
387                        }
388                        if tile_sides[j].north_east == current_sides.north_west &&
389                            tile_sides[j].south_east == current_sides.south_west {
390                            module.add_west_neighbour(j);
391                        }
392                    }
393                }
394                NeighbourKind::RelOffset(offset) => {
395                    let new_offset = (i as i32 + offset) as usize;
396                    module.add_west_neighbour(new_offset);
397                }
398            }
399            modules.push(module);
400        }
401
402        Self {
403            w,
404            h,
405            draw_scale,
406            atlas,
407            tile_width: 32,
408            tile_height: 32,
409            tiles,
410            modules,
411            texture,
412            map_data: vec![0; w*h],
413            cell_tree_data: vec![TreeType::None; w*h],
414            corner_tree_data: vec![TreeType::None; (w+1)*(h+1)]
415        }
416    }
Source

pub fn add_west_neighbour(&mut self, idx: usize)

A function which adds a neighbour on a west side

Examples found in repository?
examples/wang_corner_carpet.rs (line 129)
69    pub async fn new(w: usize, h: usize) -> Self {
70        let InternalGlContext {
71            quad_context: ctx, ..
72        } = unsafe { get_internal_gl() };
73
74        let texture_bytes = load_file("assets/wang_4_corner.png").await.unwrap();
75
76        let img = image::load_from_memory(&texture_bytes[..])
77            .unwrap_or_else(|e| panic!("{}", e))
78            .to_rgba8();
79
80        let img_w = img.width();
81        let img_h = img.height();
82
83        let texture = Texture2D::from_miniquad_texture(
84            miniquad::Texture::from_data_and_format(
85                ctx,
86                &img.into_raw(),
87                TextureParams {
88                    format: TextureFormat::RGBA8,
89                    wrap: TextureWrap::Clamp,
90                    filter: FilterMode::Nearest,
91                    width: img_w,
92                    height: img_h
93                }
94            )
95        );
96
97        let tiles = (0..=255)
98            .map(|idx| {
99                let width = 32;
100                let height = 32;
101                (
102                    idx as u8,
103                    SubRect {
104                        x: (idx % 16) * width,
105                        y: (idx / 16) * height,
106                        width,
107                        height
108                    }
109                )
110            })
111            .collect::<Vec<_>>();
112
113        let modules = tiles
114            .iter()
115            .map(|tile| {
116                let mut module: WfcModule<CustomBitSet> = WfcModule::new();
117                for i in 0..tiles.len() {
118                    let other_tile = &tiles[i];
119                    if get_north_west(tile.0) == get_south_west(other_tile.0) &&
120                        get_north_east(tile.0) == get_south_east(other_tile.0) {
121                        module.add_north_neighbour(i);
122                    }
123                    if get_south_west(tile.0) == get_north_west(other_tile.0) &&
124                        get_south_east(tile.0) == get_north_east(other_tile.0) {
125                        module.add_south_neighbour(i);
126                    }
127                    if get_north_west(tile.0) == get_north_east(other_tile.0) &&
128                        get_south_west(tile.0) == get_south_east(other_tile.0) {
129                        module.add_west_neighbour(i);
130                    }
131                    if get_north_east(tile.0) == get_north_west(other_tile.0) &&
132                        get_south_east(tile.0) == get_south_west(other_tile.0) {
133                        module.add_east_neighbour(i);
134                    }
135                }
136                module
137            })
138            .collect::<Vec<_>>();
139
140        Self {
141            w,
142            h,
143            tile_width: 32,
144            tile_height: 32,
145            tiles,
146            modules,
147            texture,
148            map_data: vec![0; w*h]
149        }
150    }
More examples
Hide additional examples
examples/dungeon.rs (line 327)
144    pub async fn new(w: usize, h: usize) -> Self {
145        let InternalGlContext {
146            quad_context: ctx, ..
147        } = unsafe { get_internal_gl() };
148
149        let dungeon_bytes = load_file("assets/dungeon_tiles.png").await.unwrap();
150
151        let img = image::load_from_memory(&dungeon_bytes[..])
152            .unwrap_or_else(|e| panic!("{}", e))
153            .to_rgba8();
154
155        let img_w = img.width();
156        let img_h = img.height();
157
158        let texture = Texture2D::from_miniquad_texture(
159            miniquad::Texture::from_data_and_format(
160                ctx,
161                &img.into_raw(),
162                TextureParams {
163                    format: TextureFormat::RGBA8,
164                    wrap: TextureWrap::Clamp,
165                    filter: FilterMode::Nearest,
166                    width: img_w,
167                    height: img_h
168                }
169            )
170        );
171
172        let tiles_bytes = load_file("assets/dungeon_tiles.ron").await.unwrap();
173        let dungeon_tiles: DungeonTiles = from_reader(&tiles_bytes[..]).unwrap();
174
175        let mut tiles = Vec::new();
176        for (kind_code, subrects) in dungeon_tiles.wang_4_corner_tiles.iter() {
177            tiles.push(Tile {
178                kind: TileKind::Wang4Corner(*kind_code),
179                subrects: subrects.clone(),
180                neighbours_east: Vec::new(),
181                neighbours_west: Vec::new(),
182                neighbours_north: Vec::new(),
183                neighbours_south: Vec::new()
184            });
185        }
186        // We need to be sure that zero tile is always a "void" tile, so we doing an extra sort step
187        tiles.sort_by(|lhs, rhs| {
188            match (lhs.kind, rhs.kind) {
189                (TileKind::Wang4Corner(kind_lhs), TileKind::Wang4Corner(kind_rhs)) => kind_lhs.cmp(&kind_rhs),
190                _ => Ordering::Equal
191            }
192        });
193
194        for i in 0..tiles.len() {
195            let current_kind = tiles[i].kind;
196            for j in 0..tiles.len() {
197                let candidate_kind = tiles[j].kind;
198                let (matches_north, matches_south, matches_east, matches_west) = {
199                    match (current_kind, candidate_kind) {
200                        (TileKind::Wang4Corner(current), TileKind::Wang4Corner(candidate)) => {
201                            (
202                                get_north_east(current) == get_south_east(candidate) &&
203                                    get_north_west(current) == get_south_west(candidate),
204
205                                get_south_east(current) == get_north_east(candidate) &&
206                                    get_south_west(current) == get_north_west(candidate),
207
208                                get_north_east(current) == get_north_west(candidate) &&
209                                    get_south_east(current) == get_south_west(candidate),
210
211                                get_north_west(current) == get_north_east(candidate) &&
212                                    get_south_west(current) == get_south_east(candidate),
213                            )
214                        },
215                        _ => continue
216                    }
217                };
218                if matches_east {
219                    tiles[i].neighbours_east.push(candidate_kind);
220                }
221                if matches_west {
222                    tiles[i].neighbours_west.push(candidate_kind);
223                }
224                if matches_north {
225                    tiles[i].neighbours_north.push(candidate_kind);
226                }
227                if matches_south {
228                    tiles[i].neighbours_south.push(candidate_kind);
229                }
230            }
231        }
232
233        //Add bridges:
234        {
235            let bridge_tiles_offset = tiles.len();
236            tiles.extend_from_slice(&dungeon_tiles.extra_tiles[..]);
237
238            let mut bridge_match_queue_south = VecDeque::new();
239            let mut bridge_match_queue_north = VecDeque::new();
240            let mut bridge_match_queue_east = VecDeque::new();
241            let mut bridge_match_queue_west = VecDeque::new();
242
243            for bridge_tile in &tiles[bridge_tiles_offset..] {
244                for south_neighbour in bridge_tile.neighbours_south.iter() {
245                    if let TileKind::Wang4Corner(kind) = south_neighbour {
246                        for i in 0..bridge_tiles_offset {
247                            match tiles[i].kind {
248                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
249                                    bridge_match_queue_south.push_back((bridge_tile.kind, i))
250                                },
251                                _ => ()
252                            };
253                        }
254                    }
255                }
256                for north_neighbour in bridge_tile.neighbours_north.iter() {
257                    if let TileKind::Wang4Corner(kind) = north_neighbour {
258                        for i in 0..bridge_tiles_offset {
259                            match tiles[i].kind {
260                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
261                                    bridge_match_queue_north.push_back((bridge_tile.kind, i))
262                                },
263                                _ => ()
264                            };
265                        }
266                    }
267                }
268                for east_neighbour in bridge_tile.neighbours_east.iter() {
269                    if let TileKind::Wang4Corner(kind) = east_neighbour {
270                        for i in 0..bridge_tiles_offset {
271                            match tiles[i].kind {
272                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
273                                    bridge_match_queue_east.push_back((bridge_tile.kind, i))
274                                },
275                                _ => ()
276                            };
277                        }
278                    }
279                }
280                for west_neighbour in bridge_tile.neighbours_west.iter() {
281                    if let TileKind::Wang4Corner(kind) = west_neighbour {
282                        for i in 0..bridge_tiles_offset {
283                            match tiles[i].kind {
284                                TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
285                                    bridge_match_queue_west.push_back((bridge_tile.kind, i))
286                                },
287                                _ => ()
288                            };
289                        }
290                    }
291                }
292            }
293
294            while !bridge_match_queue_south.is_empty() {
295                let next_match = bridge_match_queue_south.pop_front().unwrap();
296                tiles[next_match.1].neighbours_north.push(next_match.0);
297            }
298
299            while !bridge_match_queue_north.is_empty() {
300                let next_match = bridge_match_queue_north.pop_front().unwrap();
301                tiles[next_match.1].neighbours_south.push(next_match.0);
302            }
303
304            while !bridge_match_queue_east.is_empty() {
305                let next_match = bridge_match_queue_east.pop_front().unwrap();
306                tiles[next_match.1].neighbours_west.push(next_match.0);
307            }
308
309            while !bridge_match_queue_west.is_empty() {
310                let next_match = bridge_match_queue_west.pop_front().unwrap();
311                tiles[next_match.1].neighbours_east.push(next_match.0);
312            }
313        }
314
315        let modules = tiles
316            .iter()
317            .map(|tile| {
318                let mut module: WfcModule<CustomBitSet> = WfcModule::new();
319                for i in 0..tiles.len() {
320                    if tile.neighbours_north.contains(&tiles[i].kind) {
321                        module.add_north_neighbour(i);
322                    }
323                    if tile.neighbours_south.contains(&tiles[i].kind) {
324                        module.add_south_neighbour(i);
325                    }
326                    if tile.neighbours_west.contains(&tiles[i].kind) {
327                        module.add_west_neighbour(i);
328                    }
329                    if tile.neighbours_east.contains(&tiles[i].kind) {
330                        module.add_east_neighbour(i);
331                    }
332                }
333                module
334            })
335            .collect::<Vec<_>>();
336        
337        Self {
338            w,
339            h,
340            tile_width: dungeon_tiles.tile_width,
341            tile_height: dungeon_tiles.tile_height,
342            tiles,
343            modules,
344            texture,
345            map_data: vec![(0, 0); w*h]
346        }
347    }
examples/summer_garden.rs (line 390)
183    pub async fn new(w: usize, h: usize, draw_scale: f32) -> Self {
184        let InternalGlContext {
185            quad_context: ctx, ..
186        } = unsafe { get_internal_gl() };
187
188        let texture_bytes = load_file("assets/reduced_wang_scheme.png").await.unwrap();
189
190        let img = image::load_from_memory(&texture_bytes[..])
191            .unwrap_or_else(|e| panic!("{}", e))
192            .to_rgba8();
193
194        let img_w = img.width();
195        let img_h = img.height();
196
197        let texture = Texture2D::from_miniquad_texture(
198            miniquad::Texture::from_data_and_format(
199                ctx,
200                &img.into_raw(),
201                TextureParams {
202                    format: TextureFormat::RGBA8,
203                    wrap: TextureWrap::Clamp,
204                    filter: FilterMode::Nearest,
205                    width: img_w,
206                    height: img_h
207                }
208            )
209        );
210
211        let atlas_bytes = load_file("assets/reduced_wang_scheme.ron").await.unwrap();
212        let atlas: SummerGardenAtlas = from_reader(&atlas_bytes[..]).unwrap();
213
214        let mut tile_sides = Vec::new();
215        let mut neighbour_strategies = Vec::new();
216        let mut tiles = Vec::new();
217
218        {
219            for tile_cfg in atlas.terrain_tile_configs.iter() {
220                for pattern in &[
221                    &atlas.reduced_wang_patterns[..],
222                    &atlas.extended_set_1_patterns_north_west[..],
223                    &atlas.extended_set_1_patterns_north_east[..],
224                    &atlas.extended_set_1_patterns_south_west[..],
225                    &atlas.extended_set_1_patterns_south_east[..],
226                    &atlas.extended_set_2_patterns_north_west[..],
227                    &atlas.extended_set_2_patterns_north_east[..],
228                    &atlas.extended_set_2_patterns_south_west[..],
229                    &atlas.extended_set_2_patterns_south_east[..],
230                ] {
231                    tile_sides.extend(
232                        pattern.iter().map(
233                            |pattern| {
234                                TileSides {
235                                    north_west: match pattern.north_west {
236                                        TileKind::Inner => { tile_cfg.inner_type }
237                                        TileKind::Outer => { tile_cfg.outer_type }
238                                    },
239                                    north_east: match pattern.north_east {
240                                        TileKind::Inner => { tile_cfg.inner_type }
241                                        TileKind::Outer => { tile_cfg.outer_type }
242                                    },
243                                    south_west: match pattern.south_west {
244                                        TileKind::Inner => { tile_cfg.inner_type }
245                                        TileKind::Outer => { tile_cfg.outer_type }
246                                    },
247                                    south_east: match pattern.south_east {
248                                        TileKind::Inner => { tile_cfg.inner_type }
249                                        TileKind::Outer => { tile_cfg.outer_type }
250                                    }
251                                }
252                            }
253                        )
254                    );
255                }
256                for j in 0..4 {
257                    for i in 0..4 {
258                        tiles.push(SubRect{
259                            x: i * 32 + tile_cfg.x_offset,
260                            y: j * 32 + tile_cfg.y_offset,
261                            width: 32,
262                            height: 32
263                        })
264                    }
265                }
266                for jj in 0..2 {
267                    for ii in 0..2 {
268                        for j in 0..2 {
269                            for i in 0..2 {
270                                tiles.push(SubRect{
271                                    x: (i + ii * 2) * 32 + tile_cfg.x_offset + 256,
272                                    y: (j + jj * 2) * 32 + tile_cfg.y_offset,
273                                    width: 32,
274                                    height: 32
275                                })
276                            }
277                        }
278                    }
279                }
280                for jj in 0..2 {
281                    for ii in 0..2 {
282                        for j in 0..2 {
283                            for i in 0..2 {
284                                tiles.push(SubRect{
285                                    x: (i + ii * 2) * 32 + tile_cfg.x_offset,
286                                    y: (j + jj * 2) * 32 + tile_cfg.y_offset + 256,
287                                    width: 32,
288                                    height: 32
289                                })
290                            }
291                        }
292                    }
293                }
294                neighbour_strategies.extend_from_slice(&atlas.reduced_wang_neighbour_strategy[..]);
295                for _ in 0..8 {
296                    neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_2_x_2[..]);
297                }
298            }
299            tile_sides.extend_from_slice(&atlas.vertical_bridge_sides[..]);
300            tile_sides.extend_from_slice(&atlas.horizontal_bridge_sides[..]);
301            for j in 0..3 {
302                for i in 0..3 {
303                    tiles.push(SubRect{
304                        x: i * 32 + 256,
305                        y: j * 32 + 256,
306                        width: 32,
307                        height: 32
308                    })
309                }
310            }
311            for j in 0..3 {
312                for i in 0..3 {
313                    tiles.push(SubRect{
314                        x: i * 32 + 256 + 96,
315                        y: j * 32 + 256,
316                        width: 32,
317                        height: 32
318                    })
319                }
320            }
321            neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
322            neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
323
324            assert_eq!(tile_sides.len(), neighbour_strategies.len());
325        }
326
327        let mut modules = Vec::new();
328        for i in 0..tile_sides.len() {
329            let current_sides = tile_sides[i];
330            let mut module: WfcModule<CustomBitSet> = WfcModule::new();
331            match neighbour_strategies[i].north {
332                NeighbourKind::WangCorners => {
333                    for j in 0..tile_sides.len() {
334                        if neighbour_strategies[j].south != NeighbourKind::WangCorners {
335                            continue;
336                        }
337                        if tile_sides[j].south_west == current_sides.north_west &&
338                            tile_sides[j].south_east == current_sides.north_east {
339                            module.add_north_neighbour(j);
340                        }
341                    }
342                }
343                NeighbourKind::RelOffset(offset) => {
344                    let new_offset = (i as i32 + offset) as usize;
345                    module.add_north_neighbour(new_offset);
346                }
347            }
348            match neighbour_strategies[i].south {
349                NeighbourKind::WangCorners => {
350                    for j in 0..tile_sides.len() {
351                        if neighbour_strategies[j].north != NeighbourKind::WangCorners {
352                            continue;
353                        }
354                        if tile_sides[j].north_west == current_sides.south_west &&
355                            tile_sides[j].north_east == current_sides.south_east {
356                            module.add_south_neighbour(j);
357                        }
358                    }
359                }
360                NeighbourKind::RelOffset(offset) => {
361                    let new_offset = (i as i32 + offset) as usize;
362                    module.add_south_neighbour(new_offset);
363                }
364            }
365            match neighbour_strategies[i].east {
366                NeighbourKind::WangCorners => {
367                    for j in 0..tile_sides.len() {
368                        if neighbour_strategies[j].west != NeighbourKind::WangCorners {
369                            continue;
370                        }
371                        if tile_sides[j].north_west == current_sides.north_east &&
372                            tile_sides[j].south_west == current_sides.south_east {
373                            module.add_east_neighbour(j);
374                        }
375                    }
376                }
377                NeighbourKind::RelOffset(offset) => {
378                    let new_offset = (i as i32 + offset) as usize;
379                    module.add_east_neighbour(new_offset);
380                }
381            }
382            match neighbour_strategies[i].west {
383                NeighbourKind::WangCorners => {
384                    for j in 0..tile_sides.len() {
385                        if neighbour_strategies[j].east != NeighbourKind::WangCorners {
386                            continue;
387                        }
388                        if tile_sides[j].north_east == current_sides.north_west &&
389                            tile_sides[j].south_east == current_sides.south_west {
390                            module.add_west_neighbour(j);
391                        }
392                    }
393                }
394                NeighbourKind::RelOffset(offset) => {
395                    let new_offset = (i as i32 + offset) as usize;
396                    module.add_west_neighbour(new_offset);
397                }
398            }
399            modules.push(module);
400        }
401
402        Self {
403            w,
404            h,
405            draw_scale,
406            atlas,
407            tile_width: 32,
408            tile_height: 32,
409            tiles,
410            modules,
411            texture,
412            map_data: vec![0; w*h],
413            cell_tree_data: vec![TreeType::None; w*h],
414            corner_tree_data: vec![TreeType::None; (w+1)*(h+1)]
415        }
416    }

Trait Implementations§

Source§

impl<TBitSet> Clone for WfcModule<TBitSet>
where TBitSet: BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> + BitUnion<Output = TBitSet> + Clone,

Source§

fn clone(&self) -> WfcModule<TBitSet>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<TBitSet> Copy for WfcModule<TBitSet>
where TBitSet: BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> + BitUnion<Output = TBitSet> + Copy,

Auto Trait Implementations§

§

impl<TBitSet> Freeze for WfcModule<TBitSet>
where TBitSet: Freeze,

§

impl<TBitSet> RefUnwindSafe for WfcModule<TBitSet>
where TBitSet: RefUnwindSafe,

§

impl<TBitSet> Send for WfcModule<TBitSet>
where TBitSet: Send,

§

impl<TBitSet> Sync for WfcModule<TBitSet>
where TBitSet: Sync,

§

impl<TBitSet> Unpin for WfcModule<TBitSet>
where TBitSet: Unpin,

§

impl<TBitSet> UnwindSafe for WfcModule<TBitSet>
where TBitSet: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V