summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2026-08-31 00:03:32 -0700
committerKai Stevenson <kai@kaistevenson.com>2026-08-31 00:03:32 -0700
commitd68cf09f7b8e5cb783dc495097c17eaf2a4d5427 (patch)
tree59216cae8c466ad63fa6ff47dc5c7f35c64c23d2
parent8e128d3ca24fa10dc7d871f7daf6c43eaddc385c (diff)
-rw-r--r--assets/tilesets/tileset1/img.pngbin860 -> 1237 bytes
-rw-r--r--src/camera.rs2
-rw-r--r--src/content/world/mines.rs152
-rw-r--r--src/main.rs8
-rw-r--r--src/proc_gen/herringbone.rs113
-rw-r--r--src/proc_gen/mod.rs101
-rw-r--r--src/proc_gen/tileset_loader.rs53
-rw-r--r--src/sim/cell_manager/chunk.rs2
-rw-r--r--src/sim/cell_manager/manager.rs2
-rw-r--r--src/sim/entity/mod.rs2
-rw-r--r--src/sim/lib/marching_squares.rs12
-rw-r--r--src/sim/rb_manager/mod.rs2
12 files changed, 279 insertions, 170 deletions
diff --git a/assets/tilesets/tileset1/img.png b/assets/tilesets/tileset1/img.png
index e730faf..08df35d 100644
--- a/assets/tilesets/tileset1/img.png
+++ b/assets/tilesets/tileset1/img.png
Binary files differ
diff --git a/src/camera.rs b/src/camera.rs
index f5e7c1c..8d1fe78 100644
--- a/src/camera.rs
+++ b/src/camera.rs
@@ -85,7 +85,7 @@ impl Camera {
pub fn new(screen_size: (i32, i32)) -> Self {
Camera {
- zoom: 0.20,
+ zoom: 0.12,
centre: (0.0, 0.0),
screen_size,
}
diff --git a/src/content/world/mines.rs b/src/content/world/mines.rs
index ae859bc..6ed4451 100644
--- a/src/content/world/mines.rs
+++ b/src/content/world/mines.rs
@@ -1,41 +1,145 @@
+use glam::{IVec2, Vec2};
+
use crate::{
config::TILESET_SCALING,
content::materials::MaterialId,
proc_gen::{
- Biome,
- tileset_loader::{Tile, TileOrientation, TilesetPixelType},
+ Biome, TileCells,
+ tileset_loader::{Tile, TilesetPixelType},
},
- sim::cell::Cell,
+ sim::{cell::Cell, lib::marching_squares::compute_types},
};
-pub struct MinesBiome;
+const FULL: [bool; (TILESET_SCALING * TILESET_SCALING) as usize] =
+ [true; (TILESET_SCALING * TILESET_SCALING) as usize];
+
+const EMPTY: [bool; (TILESET_SCALING * TILESET_SCALING) as usize] =
+ [false; (TILESET_SCALING * TILESET_SCALING) as usize];
+
+pub struct MinesBiome {
+ pixel_expansion_by_type: [[bool; (TILESET_SCALING * TILESET_SCALING) as usize]; 16],
+}
+
+fn circular_pixel_expansion(
+ c: Vec2,
+ r: f32,
+) -> [bool; (TILESET_SCALING * TILESET_SCALING) as usize] {
+ let rs = r.powi(2);
+ let mut ret = [false; (TILESET_SCALING * TILESET_SCALING) as usize];
+
+ for y in 0..TILESET_SCALING {
+ for x in 0..TILESET_SCALING {
+ // definitely can be optimized a lot
+ let dist = Vec2::new(x as f32, y as f32).distance_squared(c);
+ if dist <= rs {
+ ret[(x + y * TILESET_SCALING) as usize] = true;
+ }
+ }
+ }
+
+ ret
+}
+
+impl MinesBiome {
+ pub fn new() -> Self {
+ MinesBiome {
+ pixel_expansion_by_type: [
+ // empty
+ EMPTY,
+ // BL
+ circular_pixel_expansion(
+ Vec2::new(0.0, TILESET_SCALING as f32 - 1.0),
+ TILESET_SCALING as f32,
+ ),
+ // BR
+ circular_pixel_expansion(
+ Vec2::new(TILESET_SCALING as f32 - 1.0, TILESET_SCALING as f32 - 1.0),
+ TILESET_SCALING as f32,
+ ),
+ // BL BR
+ FULL,
+ // TR
+ circular_pixel_expansion(
+ Vec2::new(TILESET_SCALING as f32 - 1.0, 0.0),
+ TILESET_SCALING as f32,
+ ),
+ // TR BL
+ FULL,
+ // TR BR
+ FULL,
+ // TR BR BL
+ FULL,
+ // TL
+ circular_pixel_expansion(Vec2::new(0.0, 0.0), TILESET_SCALING as f32),
+ // TL BL
+ FULL,
+ // TL BR
+ FULL,
+ // TL BR BL
+ FULL,
+ // TL TR
+ FULL,
+ // TL TR BL
+ FULL,
+ // TL TR BR
+ FULL,
+ // surrounded
+ FULL,
+ ],
+ }
+ }
+}
impl Biome for MinesBiome {
- fn derive_world_from_tile(&self, tile: &Tile) -> Vec<Cell> {
- let tp = TILESET_SCALING.pow(2) as u32;
- let mut cells =
- vec![Cell::void(); (tile.dimensions.short * tile.dimensions.long * tp) as usize];
- let ey = match tile.orientation {
- TileOrientation::Horizontal => tile.dimensions.short,
- TileOrientation::Vertical => tile.dimensions.long,
- };
- let ex = match tile.orientation {
- TileOrientation::Horizontal => tile.dimensions.long,
- TileOrientation::Vertical => tile.dimensions.short,
- };
+ fn derive_world_from_tile(&self, tile: &Tile) -> TileCells {
+ let pixels = tile.size();
+ let marched_pixels = compute_types(tile);
+ let size = pixels * TILESET_SCALING;
+ let mut cells = vec![Cell::void(); (size.x * size.y) as usize];
- for y in 0..ey {
- for x in 0..ex {
- let idx = (x + y * ex) * tp;
- for i in 0..tp {
- cells[(idx + i) as usize] = match tile.pixels[(x + y * ex) as usize] {
- TilesetPixelType::Void => Cell::void(),
- TilesetPixelType::Terrain => Cell::from_material(MaterialId::Dirt),
+ for py in 0..pixels.y {
+ for px in 0..pixels.x {
+ let pixel = tile.pixel_at(IVec2::new(px, py));
+ let variant = marched_pixels[(px + py * (pixels.x + 1)) as usize];
+
+ // let pix = marched_pixels[(px + py * pixels.x) as usize];
+ // let expansion_cells = [Cell::from_material(MaterialId::from_index(
+ // pix % MaterialId::ALL.len() as u8,
+ // ));
+ // (TILESET_SCALING * TILESET_SCALING) as usize];
+
+ // let origin = IVec2::new(px, py) * TILESET_SCALING;
+ // for i in 0..TILESET_SCALING {
+ // let y = i + origin.y;
+ // let row = (y * size.x + origin.x) as usize;
+ // cells[row..row + TILESET_SCALING as usize].copy_from_slice(
+ // &expansion_cells[i as usize..i as usize + TILESET_SCALING as usize],
+ // );
+ // }
+
+ let expansion = self.pixel_expansion_by_type[variant as usize];
+ // TODO optimize
+ let expansion_cells = expansion.map(|c| {
+ if c {
+ Cell::from_material(MaterialId::Dirt)
+ } else {
+ Cell::void()
}
+ });
+
+ let origin = IVec2::new(px, py) * TILESET_SCALING;
+ for i in 0..TILESET_SCALING {
+ let dst_y = i + origin.y;
+ let dst_row = (dst_y * size.x + origin.x) as usize;
+ let src_row = (i * TILESET_SCALING) as usize;
+
+ cells[dst_row..dst_row + TILESET_SCALING as usize].copy_from_slice(
+ &expansion_cells[src_row..src_row + TILESET_SCALING as usize],
+ );
}
}
}
- cells
+ TileCells { size, cells }
}
}
diff --git a/src/main.rs b/src/main.rs
index 118f2a4..e9cae2d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -150,7 +150,7 @@ impl Default for App {
sim_manager: Some(SimManager::new()),
world_generator: TilesetWorldGenerator::new(
"assets/tilesets/tileset1",
- Box::new(MinesBiome),
+ &MinesBiome::new(),
),
last_render: Instant::now(),
@@ -168,7 +168,11 @@ impl ApplicationHandler for App {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
let window = Arc::new(
event_loop
- .create_window(Window::default_attributes().with_title(WINDOW_TITLE))
+ .create_window(
+ Window::default_attributes()
+ .with_title(WINDOW_TITLE)
+ .with_maximized(true),
+ )
.unwrap(),
);
diff --git a/src/proc_gen/herringbone.rs b/src/proc_gen/herringbone.rs
index 271b7a1..e8569c8 100644
--- a/src/proc_gen/herringbone.rs
+++ b/src/proc_gen/herringbone.rs
@@ -1,111 +1,30 @@
use fxhash::hash32;
use glam::IVec2;
-use crate::{
- config::TILESET_SCALING,
- proc_gen::tileset_loader::{Tile, TileOrientation, Tileset, TilesetPixelType},
-};
+use crate::proc_gen::tileset_loader::TileOrientation;
-pub fn split_position(world: IVec2, tileset: &Tileset) -> (IVec2, IVec2, TileOrientation) {
- let s = tileset.dimensions.short as i32;
- let tx = world.x.div_euclid(s);
- let ty = world.y.div_euclid(s);
- let fx = world.x.rem_euclid(s);
- let fy = world.y.rem_euclid(s);
-
- match (tx - ty).rem_euclid(4) {
- // left half of horizontal tile
- 0 => (
- IVec2::new(tx, ty),
- IVec2::new(fx, fy),
- TileOrientation::Horizontal,
- ),
- // right half of horizontal tile
- 1 => (
- IVec2::new(tx - 1, ty),
- IVec2::new(fx + s, fy),
- TileOrientation::Horizontal,
- ),
- // top half of vertical tile
- 3 => (
- IVec2::new(tx, ty),
- IVec2::new(fx, fy),
- TileOrientation::Vertical,
- ),
- // bottom half of vertical tile
- 2 => (
- IVec2::new(tx, ty - 1),
- IVec2::new(fx, fy + s),
- TileOrientation::Vertical,
- ),
- _ => unreachable!(),
+fn tile_starting_at(grid: IVec2) -> Option<TileOrientation> {
+ match (grid.x - grid.y).rem_euclid(4) {
+ // 1 is the right half of the horizontal tile starting at 0,
+ // 2 is the bottom half of the vertical tile starting at 3
+ 0 => Some(TileOrientation::Horizontal),
+ 3 => Some(TileOrientation::Vertical),
+ _ => None,
}
}
+pub fn tiles_overlapping(min: IVec2, max: IVec2) -> impl Iterator<Item = (IVec2, TileOrientation)> {
+ ((min.y - 1)..max.y)
+ .flat_map(move |y| ((min.x - 1)..max.x).map(move |x| IVec2::new(x, y)))
+ .filter_map(|grid| tile_starting_at(grid).map(|orientation| (grid, orientation)))
+}
+
// better "%" for hashes since it prefers the high bits
#[inline]
fn reduce(h: u32, n: usize) -> usize {
(((h as u128) * (n as u128)) >> 32) as usize
}
-fn pick_variant(tile_pos: IVec2, orientation: TileOrientation, tileset: &Tileset) -> &Tile {
- let h = hash32(&tile_pos);
- match orientation {
- TileOrientation::Horizontal => {
- &tileset.horizontal_tiles[reduce(h, tileset.horizontal_tiles.len())]
- }
- TileOrientation::Vertical => {
- &tileset.vertical_tiles[reduce(h, tileset.vertical_tiles.len())]
- }
- }
-}
-
-// TODO: optimize
-fn get_pixel_at_position(world: IVec2, tileset: &Tileset) -> TilesetPixelType {
- let scaled_world = world.div_euclid(IVec2::new(TILESET_SCALING, TILESET_SCALING));
- let (tile_pos, local, orientation) = split_position(scaled_world, tileset);
- let tile = pick_variant(tile_pos, orientation, tileset);
- let width = match orientation {
- TileOrientation::Horizontal => tileset.dimensions.long as i32,
- TileOrientation::Vertical => tileset.dimensions.short as i32,
- };
- tile.pixels[(local.x + local.y * width) as usize]
+pub fn variant_index(grid: IVec2, variants: usize) -> usize {
+ reduce(hash32(&grid), variants)
}
-
-pub fn tiles_overlapping(
- a: IVec2,
- b: IVec2,
- tileset: &Tileset,
-) -> impl Iterator<Item = (IVec2, &Tile, TileOrientation)> {
- let s = IVec2::new(
- tileset.dimensions.short as i32,
- tileset.dimensions.short as i32,
- );
-
- let ta = a.div_euclid(s) - 1;
- let tb = (b - 1).div_euclid(s);
-
- (ta.y..=tb.y)
- .flat_map(move |ty| (ta.x..=tb.x).map(move |tx| (tx, ty)))
- .filter_map(move |(tx, ty)| match (tx - ty).rem_euclid(4) {
- 0 => Some((
- IVec2::new(tx, ty),
- pick_variant(IVec2::new(tx, ty), TileOrientation::Horizontal, tileset),
- TileOrientation::Horizontal,
- )),
- 3 => Some((
- IVec2::new(tx, ty),
- pick_variant(IVec2::new(tx, ty), TileOrientation::Vertical, tileset),
- TileOrientation::Vertical,
- )),
- _ => None,
- })
-}
-
-// pub fn get_cell_at_position(world: IVec2, tileset: &Tileset) -> Cell {
-// let pixel = get_pixel_at_position(world, tileset);
-// match pixel {
-// TilesetPixelType::Void => Cell::void(),
-// TilesetPixelType::Terrain => Cell::from_material(MaterialId::Dirt),
-// }
-// }
diff --git a/src/proc_gen/mod.rs b/src/proc_gen/mod.rs
index 049ad1a..caec241 100644
--- a/src/proc_gen/mod.rs
+++ b/src/proc_gen/mod.rs
@@ -6,66 +6,97 @@ use glam::IVec2;
use crate::{
config::{CHUNK_SIZE, TILESET_SCALING},
proc_gen::{
- herringbone::tiles_overlapping,
+ herringbone::{tiles_overlapping, variant_index},
tileset_loader::{Tile, TileOrientation, Tileset, load_tileset},
},
sim::{cell::Cell, cell_manager::chunk::Chunk, entity::EntityDef},
};
+pub struct TileCells {
+ pub size: IVec2,
+ pub cells: Vec<Cell>,
+}
+
pub trait Biome {
- fn derive_world_from_tile(&self, _tile: &Tile) -> Vec<Cell> {
- Vec::new()
- }
- fn derive_entities_from_tile(&self, _tile: &Tile) -> Vec<EntityDef> {
+ fn derive_world_from_tile(&self, tile: &Tile) -> TileCells;
+ fn derive_entities_from_tile(&self, tile: &Tile) -> Vec<EntityDef> {
Vec::new()
}
}
pub struct TilesetWorldGenerator {
tileset: Tileset,
- biome: Box<dyn Biome>,
+ horizontal_tiles: Vec<TileCells>,
+ vertical_tiles: Vec<TileCells>,
}
impl TilesetWorldGenerator {
+ pub fn new(tileset_path: &str, biome: &dyn Biome) -> Self {
+ let tileset = load_tileset(tileset_path);
+
+ let horizontal_tiles = tileset
+ .horizontal_tiles
+ .iter()
+ .map(|tile| biome.derive_world_from_tile(tile))
+ .collect();
+ let vertical_tiles = tileset
+ .vertical_tiles
+ .iter()
+ .map(|tile| biome.derive_world_from_tile(tile))
+ .collect();
+
+ TilesetWorldGenerator {
+ tileset,
+ horizontal_tiles,
+ vertical_tiles,
+ }
+ }
+
+ fn grid_size(&self) -> IVec2 {
+ IVec2::splat(self.tileset.dimensions.short as i32 * TILESET_SCALING)
+ }
+
+ fn tile_at(&self, grid: IVec2, orientation: TileOrientation) -> &TileCells {
+ let tiles = match orientation {
+ TileOrientation::Horizontal => &self.horizontal_tiles,
+ TileOrientation::Vertical => &self.vertical_tiles,
+ };
+ &tiles[variant_index(grid, tiles.len())]
+ }
+
pub fn generate_chunk(&self, chunk_position: IVec2) -> Chunk {
let mut chunk = Chunk::void();
- let a = chunk_position * CHUNK_SIZE;
- let b = (chunk_position + 1) * CHUNK_SIZE;
- let tiles = tiles_overlapping(a * TILESET_SCALING, b * TILESET_SCALING, &self.tileset);
- let world_tiles = tiles.map(|(p, t, o)| (p, self.biome.derive_world_from_tile(t), o));
+ let chunk_min = chunk_position * CHUNK_SIZE;
+ let chunk_max = chunk_min + CHUNK_SIZE;
+
+ let grid = self.grid_size();
+ let tiles = tiles_overlapping(
+ chunk_min.div_euclid(grid),
+ (chunk_max - 1).div_euclid(grid) + 1,
+ );
+
+ for (grid_position, orientation) in tiles {
+ let tile = self.tile_at(grid_position, orientation);
+ let tile_min = grid_position * grid;
- for (tp, t, o) in world_tiles {
- let p = tp * self.tileset.dimensions.short as i32 * TILESET_SCALING;
- let ta = p.max(a);
- let tb = p.min(b);
- if ta.x >= tb.x || ta.y >= tb.y {
+ // subset of tile in chunk
+ let min = tile_min.max(chunk_min);
+ let max = (tile_min + tile.size).min(chunk_max);
+ if min.x >= max.x {
continue;
}
+ let width = (max.x - min.x) as usize;
- for y in ta.y..tb.y {
- for x in ta.x..tb.x {
- let sw = match o {
- TileOrientation::Horizontal => {
- self.tileset.dimensions.long as i32 * TILESET_SCALING
- }
- TileOrientation::Vertical => {
- self.tileset.dimensions.short as i32 * TILESET_SCALING
- }
- };
-
- let src = (y - p.y) * sw + (x - p.x);
- let dst = (y - a.y) * CHUNK_SIZE + (x - a.x);
- chunk.cells[dst as usize] = t[src as usize];
- }
+ for y in min.y..max.y {
+ let src = ((y - tile_min.y) * tile.size.x + (min.x - tile_min.x)) as usize;
+ let dst = ((y - chunk_min.y) * CHUNK_SIZE + (min.x - chunk_min.x)) as usize;
+ chunk.cells[dst..dst + width].copy_from_slice(&tile.cells[src..src + width]);
}
}
- chunk
- }
+ chunk.mark_collider_dirty(0);
- pub fn new(tileset_path: &str, biome: Box<dyn Biome>) -> Self {
- let tileset = load_tileset(tileset_path);
- TilesetWorldGenerator { tileset, biome }
+ chunk
}
}
diff --git a/src/proc_gen/tileset_loader.rs b/src/proc_gen/tileset_loader.rs
index acb4d65..e0d9d18 100644
--- a/src/proc_gen/tileset_loader.rs
+++ b/src/proc_gen/tileset_loader.rs
@@ -1,6 +1,9 @@
+use glam::IVec2;
use serde::Deserialize;
use std::{collections::HashMap, error::Error, fs::File, io::BufReader, path::Path};
+use crate::sim::lib::marching_squares::Marchable;
+
fn load_img(path: &Path) -> Result<(Vec<u8>, u32, u32), Box<dyn Error>> {
let mut decoder = png::Decoder::new(BufReader::new(File::open(path)?));
decoder.set_transformations(png::Transformations::IDENTITY);
@@ -32,7 +35,7 @@ pub struct TileDimensions {
pub long: u32,
}
-#[derive(Deserialize, Clone, Copy, Debug)]
+#[derive(Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
pub enum TilesetPixelType {
Void = 0,
Terrain,
@@ -55,6 +58,54 @@ pub struct Tile {
pub pixels: Vec<TilesetPixelType>,
}
+// TODO might want to use newtypes to hoist to biome
+impl Marchable for Tile {
+ fn occupied(&self, pos: IVec2) -> bool {
+ // TODO this will break for tileset dimensions other than 22x44
+ if pos.x < 0 || pos.x >= self.size().x || pos.y < 0 || pos.y >= self.size().y {
+ match self.orientation {
+ TileOrientation::Horizontal => {
+ let a = (pos.x == -1 || pos.x == (self.dimensions.long as i32))
+ && pos.y >= 8
+ && pos.y <= 13;
+ let b = (pos.y == -1 || pos.y == (self.dimensions.short as i32))
+ && ((pos.x >= 8 && pos.x <= 13) || (pos.x >= 30 && pos.x <= 35));
+ !(a || b)
+ }
+ TileOrientation::Vertical => {
+ let a = (pos.y == -1 || pos.y == (self.dimensions.long as i32))
+ && pos.x >= 8
+ && pos.x <= 13;
+ let b = (pos.x == -1 || pos.x == (self.dimensions.short as i32))
+ && ((pos.y >= 8 && pos.y <= 13) || (pos.y >= 30 && pos.y <= 35));
+ !(a || b)
+ }
+ }
+ } else {
+ self.pixel_at(pos) == TilesetPixelType::Terrain
+ }
+ }
+ fn marchable_size(&self) -> IVec2 {
+ self.size()
+ }
+}
+
+impl Tile {
+ pub fn size(&self) -> IVec2 {
+ let short = self.dimensions.short as i32;
+ let long = self.dimensions.long as i32;
+ match self.orientation {
+ TileOrientation::Horizontal => IVec2::new(long, short),
+ TileOrientation::Vertical => IVec2::new(short, long),
+ }
+ }
+
+ #[inline]
+ pub fn pixel_at(&self, position: IVec2) -> TilesetPixelType {
+ self.pixels[(position.x + position.y * self.size().x) as usize]
+ }
+}
+
#[derive(Debug)]
pub struct Tileset {
pub dimensions: TileDimensions,
diff --git a/src/sim/cell_manager/chunk.rs b/src/sim/cell_manager/chunk.rs
index 48e9d16..2021b97 100644
--- a/src/sim/cell_manager/chunk.rs
+++ b/src/sim/cell_manager/chunk.rs
@@ -72,7 +72,7 @@ impl Marchable for Chunk {
|| material.form == MaterialForm::Powder && cell.settled() >= SETTLED_THRESOHLD
}
}
- fn size(&self) -> IVec2 {
+ fn marchable_size(&self) -> IVec2 {
IVec2::new(CHUNK_SIZE, CHUNK_SIZE)
}
}
diff --git a/src/sim/cell_manager/manager.rs b/src/sim/cell_manager/manager.rs
index 157499d..7478995 100644
--- a/src/sim/cell_manager/manager.rs
+++ b/src/sim/cell_manager/manager.rs
@@ -43,7 +43,7 @@ impl CellManager {
if !sleeping {
self.chunks[idx].sleeping = false;
// remove this
- self.chunks[idx].collider_dirty_seqno = Some(0);
+ self.chunks[idx].mark_collider_dirty(0);
}
self.chunks[idx].needs_texture_update = true;
}
diff --git a/src/sim/entity/mod.rs b/src/sim/entity/mod.rs
index 2f4034b..9425f9b 100644
--- a/src/sim/entity/mod.rs
+++ b/src/sim/entity/mod.rs
@@ -44,7 +44,7 @@ impl Marchable for EntityCells {
self.get_cell_at_local_position(pos).material != MaterialId::Void
}
}
- fn size(&self) -> IVec2 {
+ fn marchable_size(&self) -> IVec2 {
self.size
}
}
diff --git a/src/sim/lib/marching_squares.rs b/src/sim/lib/marching_squares.rs
index ff48fd5..438b16c 100644
--- a/src/sim/lib/marching_squares.rs
+++ b/src/sim/lib/marching_squares.rs
@@ -43,15 +43,15 @@ fn derive_type(tl: bool, tr: bool, br: bool, bl: bool) -> usize {
pub trait Marchable {
fn occupied(&self, pos: IVec2) -> bool;
- fn size(&self) -> IVec2;
+ fn marchable_size(&self) -> IVec2;
}
-pub fn compute_types(marchable: &impl Marchable, w: i32, h: i32) -> Vec<u8> {
+pub fn compute_types(marchable: &impl Marchable) -> Vec<u8> {
// TODO could pre-allocate size
let mut types = Vec::new();
- for y in -1..h {
+ for y in -1..marchable.marchable_size().y {
// TODO precompute per column
- for x in -1..w {
+ for x in -1..marchable.marchable_size().x {
let tl = marchable.occupied(IVec2::new(x, y));
let tr = marchable.occupied(IVec2::new(x + 1, y));
let br = marchable.occupied(IVec2::new(x + 1, y + 1));
@@ -133,11 +133,11 @@ fn toward_side(x: i32, y: i32, exit: Side) -> (i32, i32, Side) {
// outer is cw, inner ccw
pub fn marching_squares_vertex_trace(marchable: &impl Marchable) -> Vec<Vec<Vec2>> {
- let [w, h] = marchable.size().to_array();
+ let [w, h] = marchable.marchable_size().to_array();
let mut visited = vec![0u8; ((w + 1) * (h + 1)) as usize];
let idx = |cx: i32, cy: i32| (((cy + 1) * (w + 1)) + (cx + 1)) as usize;
- let types = compute_types(marchable, w, h);
+ let types = compute_types(marchable);
let mut polys = Vec::new();
for y in -1..h {
diff --git a/src/sim/rb_manager/mod.rs b/src/sim/rb_manager/mod.rs
index 9d183db..2b476d5 100644
--- a/src/sim/rb_manager/mod.rs
+++ b/src/sim/rb_manager/mod.rs
@@ -110,7 +110,7 @@ impl RbManager {
let minimum_verts = minimum_verts_per_poly.unwrap_or(3);
- let centre_offset = (marchable.size() / 2).as_vec2() - 0.5;
+ let centre_offset = (marchable.marchable_size() / 2).as_vec2() - 0.5;
for poly in polys {
let v = vertices.len() as u32;