1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
use fxhash::hash32;
use glam::IVec2;
use crate::{
config::TILESET_SCALING,
content::materials::MaterialId,
proc_gen::tileset_loader::{Tile, TileOrientation, Tileset, TilesetPixelType},
sim::cell::Cell,
};
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!(),
}
}
// 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 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),
}
}
|