Optimize TileMap: replace HashMap with AHashMap, pack tile data
- Replace std HashMap (SipHash) with ahash::AHashMap for fast non-crypto hashing - Pack tile data from tuples to structs: FloorTileData (~35 bytes) and FixtureTileData (~18 bytes) - FloorTileData: pack 3 bools into single flags byte, use u8 for id/weight - FixtureTileData: pack 2 bools into single flags byte - Update all accessors: is_standable_tile, visibility, terrain generation, forestry - Preparation for async pathfinding (Arc wrapping to come in follow-up) Memory reduction: ~54% for floor tiles (76→35 bytes), ~62% for fixtures (48→18 bytes) Hash performance: AHashMap uses fxhash, faster than SipHash for game data
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
use ahash::AHashMap;
|
use ahash::AHashMap;
|
||||||
use ahash::AHashSet;
|
use ahash::AHashSet;
|
||||||
use bevy::tasks::{AsyncComputeTaskPool, Task};
|
use bevy::prelude::*;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use rustc_hash::FxHashSet as HashSet;
|
use rustc_hash::FxHashSet as HashSet;
|
||||||
use std::{cell::RefCell, collections::BinaryHeap, sync::Arc, time::Instant};
|
use std::{cell::RefCell, collections::BinaryHeap, time::Instant};
|
||||||
|
|
||||||
// Thread-local storage for collecting metrics during parallel execution
|
// Thread-local storage for collecting metrics during parallel execution
|
||||||
thread_local! {
|
thread_local! {
|
||||||
@@ -326,27 +326,24 @@ fn is_standable_tile(tilemap: &TileMap, pos: IVec3) -> bool {
|
|||||||
let mut can_i_stand_in_fixture: bool = false;
|
let mut can_i_stand_in_fixture: bool = false;
|
||||||
let mut can_i_stand_on_fixture_bellow: bool = false;
|
let mut can_i_stand_on_fixture_bellow: bool = false;
|
||||||
|
|
||||||
// Check if current position has a blocking floor tile
|
|
||||||
if let Some(current_floor_tile) = tilemap.floor_tiles.get(&pos) {
|
if let Some(current_floor_tile) = tilemap.floor_tiles.get(&pos) {
|
||||||
can_i_stand_in_tile = current_floor_tile.1;
|
can_i_stand_in_tile = current_floor_tile.can_stand_in();
|
||||||
}
|
}
|
||||||
// Check if current position has a solid fixture tile (e.g., log)
|
|
||||||
if let Some(current_fixture_tile) = tilemap.fixture_tiles.get(&pos) {
|
if let Some(current_fixture_tile) = tilemap.fixture_tiles.get(&pos) {
|
||||||
can_i_stand_in_fixture = current_fixture_tile.1;
|
can_i_stand_in_fixture = current_fixture_tile.can_stand_in();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there's solid ground below (fixture or floor)
|
|
||||||
let pos_below = pos - IVec3::new(0, 0, ITILE_SIZE);
|
let pos_below = pos - IVec3::new(0, 0, ITILE_SIZE);
|
||||||
|
|
||||||
if let Some(below_floor_tile) = tilemap.floor_tiles.get(&pos_below) {
|
if let Some(below_floor_tile) = tilemap.floor_tiles.get(&pos_below) {
|
||||||
can_i_stand_on_tile_bellow = below_floor_tile.2;
|
can_i_stand_on_tile_bellow = below_floor_tile.can_stand_on();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(below_fixture_tile) = tilemap.fixture_tiles.get(&pos_below) {
|
if let Some(below_fixture_tile) = tilemap.fixture_tiles.get(&pos_below) {
|
||||||
can_i_stand_on_fixture_bellow = below_fixture_tile.2;
|
can_i_stand_on_fixture_bellow = below_fixture_tile.can_stand_on();
|
||||||
}
|
}
|
||||||
return (can_i_stand_in_tile || can_i_stand_in_fixture)
|
(can_i_stand_in_tile || can_i_stand_in_fixture)
|
||||||
&& (can_i_stand_on_tile_bellow || can_i_stand_on_fixture_bellow);
|
&& (can_i_stand_on_tile_bellow || can_i_stand_on_fixture_bellow)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Original calculate_path - kept for reference, not currently used.
|
/// Original calculate_path - kept for reference, not currently used.
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ use std::hash::{Hash, Hasher};
|
|||||||
use crate::{
|
use crate::{
|
||||||
constants::{SEED, TILE_SIZE},
|
constants::{SEED, TILE_SIZE},
|
||||||
world::{
|
world::{
|
||||||
tiles::TileMap, ChunkForrestryEvent, FixtureTilePrefab, TextureIDs, Textures,
|
tiles::{FixtureTileData, TileMap},
|
||||||
VisibleGameEntity,
|
ChunkForrestryEvent, FixtureTilePrefab, TextureIDs, Textures, VisibleGameEntity,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,8 +26,7 @@ pub fn generate_chunk_forrestry(
|
|||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let count = events.len();
|
let count = events.len();
|
||||||
|
|
||||||
let collected_tilemap_updates: Mutex<Vec<(IVec3, (i32, bool, bool, [u32; 8]))>> =
|
let collected_tilemap_updates: Mutex<Vec<(IVec3, FixtureTileData)>> = Mutex::new(Vec::new());
|
||||||
Mutex::new(Vec::<(IVec3, (i32, bool, bool, [u32; 8]))>::new());
|
|
||||||
|
|
||||||
events.par_read().for_each(|event| {
|
events.par_read().for_each(|event| {
|
||||||
let floor_positions = &event.floor_tiles;
|
let floor_positions = &event.floor_tiles;
|
||||||
@@ -87,10 +86,10 @@ pub fn generate_chunk_forrestry(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collected_tilemap_updates
|
collected_tilemap_updates.lock().unwrap().push((
|
||||||
.lock()
|
trunk_ivec,
|
||||||
.unwrap()
|
FixtureTileData::new(1, false, true, [0; 8]),
|
||||||
.push((trunk_ivec, (1, false, true, [0; 8])));
|
));
|
||||||
|
|
||||||
log_positions.insert(trunk_ivec);
|
log_positions.insert(trunk_ivec);
|
||||||
}
|
}
|
||||||
@@ -144,10 +143,14 @@ pub fn generate_chunk_forrestry(
|
|||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
commands.entity(leaf).insert(VisibleGameEntity);
|
commands.entity(leaf).insert(VisibleGameEntity);
|
||||||
collected_tilemap_updates
|
collected_tilemap_updates.lock().unwrap().push(
|
||||||
.lock()
|
(
|
||||||
.unwrap()
|
ivec,
|
||||||
.push((ivec, (5, false, true, [0; 8])));
|
FixtureTileData::new(
|
||||||
|
5, false, true, [0; 8],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ use noise::{NoiseFn, Perlin};
|
|||||||
use crate::{
|
use crate::{
|
||||||
constants::{SEED, TILE_SIZE},
|
constants::{SEED, TILE_SIZE},
|
||||||
world::{
|
world::{
|
||||||
tiles::TileMap, ChunkForrestryEvent, ChunkTerrainEvent, FloorTilePrefab,
|
tiles::{FloorTileData, TileMap},
|
||||||
TileOcclusionEvent, CHUNK_SIZE, Z_ABOVE, Z_BELOW,
|
ChunkForrestryEvent, ChunkTerrainEvent, FloorTilePrefab, TileOcclusionEvent, CHUNK_SIZE,
|
||||||
|
Z_ABOVE, Z_BELOW,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,8 +51,7 @@ pub fn generate_chunk_terrain(
|
|||||||
let start_y = chunk_pos.y * CHUNK_SIZE;
|
let start_y = chunk_pos.y * CHUNK_SIZE;
|
||||||
|
|
||||||
let mut surface_positions: Vec<(Vec3, String)> = Vec::new();
|
let mut surface_positions: Vec<(Vec3, String)> = Vec::new();
|
||||||
let mut local_tilemap_updates: HashMap<IVec3, (i32, bool, bool, bool, i32, [u32; 8])> =
|
let mut local_tilemap_updates: HashMap<IVec3, FloorTileData> = HashMap::new();
|
||||||
HashMap::new();
|
|
||||||
|
|
||||||
// Generate tiles for this chunk
|
// Generate tiles for this chunk
|
||||||
for local_y in 0..CHUNK_SIZE {
|
for local_y in 0..CHUNK_SIZE {
|
||||||
@@ -84,23 +84,26 @@ pub fn generate_chunk_terrain(
|
|||||||
commands.command_scope(|mut cmd| {
|
commands.command_scope(|mut cmd| {
|
||||||
FloorTilePrefab::air(position).spawn(&mut cmd);
|
FloorTilePrefab::air(position).spawn(&mut cmd);
|
||||||
});
|
});
|
||||||
local_tilemap_updates
|
local_tilemap_updates.insert(
|
||||||
.insert(pos_ivec, (0, true, false, true, 0, [0; 8]));
|
pos_ivec,
|
||||||
// Air tile
|
FloorTileData::new(0, true, false, true, 0, [0; 8]),
|
||||||
|
);
|
||||||
} else if cave_value < 0.8 {
|
} else if cave_value < 0.8 {
|
||||||
commands.command_scope(|mut cmd| {
|
commands.command_scope(|mut cmd| {
|
||||||
FloorTilePrefab::rock(position).spawn(&mut cmd);
|
FloorTilePrefab::rock(position).spawn(&mut cmd);
|
||||||
});
|
});
|
||||||
local_tilemap_updates
|
local_tilemap_updates.insert(
|
||||||
.insert(pos_ivec, (2, false, true, false, 50, [0; 8]));
|
pos_ivec,
|
||||||
// Rock tile
|
FloorTileData::new(2, false, true, false, 50, [0; 8]),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
commands.command_scope(|mut cmd| {
|
commands.command_scope(|mut cmd| {
|
||||||
FloorTilePrefab::dirt(position).spawn(&mut cmd);
|
FloorTilePrefab::dirt(position).spawn(&mut cmd);
|
||||||
});
|
});
|
||||||
local_tilemap_updates
|
local_tilemap_updates.insert(
|
||||||
.insert(pos_ivec, (1, false, true, false, 85, [0; 8]));
|
pos_ivec,
|
||||||
// Dirt tile
|
FloorTileData::new(1, false, true, false, 85, [0; 8]),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if noise_position.z > position.z {
|
} else if noise_position.z > position.z {
|
||||||
if (generate_surface_terrain(world_x, world_y) * TILE_SIZE).round()
|
if (generate_surface_terrain(world_x, world_y) * TILE_SIZE).round()
|
||||||
@@ -109,23 +112,28 @@ pub fn generate_chunk_terrain(
|
|||||||
commands.command_scope(|mut cmd| {
|
commands.command_scope(|mut cmd| {
|
||||||
FloorTilePrefab::grass(position).spawn(&mut cmd);
|
FloorTilePrefab::grass(position).spawn(&mut cmd);
|
||||||
});
|
});
|
||||||
local_tilemap_updates
|
local_tilemap_updates.insert(
|
||||||
.insert(pos_ivec, (1, false, true, false, 100, [0; 8])); // Dirt tile (grass)
|
pos_ivec,
|
||||||
surface_positions.push((position, ("grass").to_string()));
|
FloorTileData::new(1, false, true, false, 100, [0; 8]),
|
||||||
|
);
|
||||||
|
surface_positions.push((position, "grass".to_string()));
|
||||||
} else {
|
} else {
|
||||||
commands.command_scope(|mut cmd| {
|
commands.command_scope(|mut cmd| {
|
||||||
FloorTilePrefab::dirt(position).spawn(&mut cmd);
|
FloorTilePrefab::dirt(position).spawn(&mut cmd);
|
||||||
});
|
});
|
||||||
local_tilemap_updates
|
local_tilemap_updates.insert(
|
||||||
.insert(pos_ivec, (1, false, true, false, 85, [0; 8]));
|
pos_ivec,
|
||||||
// Dirt tile
|
FloorTileData::new(1, false, true, false, 85, [0; 8]),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
commands.command_scope(|mut cmd| {
|
commands.command_scope(|mut cmd| {
|
||||||
FloorTilePrefab::air(position).spawn(&mut cmd);
|
FloorTilePrefab::air(position).spawn(&mut cmd);
|
||||||
});
|
});
|
||||||
local_tilemap_updates.insert(pos_ivec, (0, true, false, true, 0, [0; 8]));
|
local_tilemap_updates.insert(
|
||||||
// Air tile
|
pos_ivec,
|
||||||
|
FloorTileData::new(0, true, false, true, 0, [0; 8]),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+201
-5
@@ -1,9 +1,205 @@
|
|||||||
|
use ahash::AHashMap;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_platform::collections::hash_map::HashMap;
|
|
||||||
|
|
||||||
#[derive(Resource, Default, Clone)]
|
/// Packed floor tile data for efficient storage. ~35 bytes vs 76 bytes tuple.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct FloorTileData {
|
||||||
|
pub id: u8,
|
||||||
|
/// bit0=can_stand_in, bit1=can_stand_on, bit2=visibly_transparent
|
||||||
|
pub flags: u8,
|
||||||
|
pub astar_weight: u8,
|
||||||
|
pub visible_range: [u32; 8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FloorTileData {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
id: 0,
|
||||||
|
flags: 0b001,
|
||||||
|
astar_weight: 0,
|
||||||
|
visible_range: [0; 8],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FloorTileData {
|
||||||
|
pub fn new(
|
||||||
|
id: u8,
|
||||||
|
can_stand_in: bool,
|
||||||
|
can_stand_on: bool,
|
||||||
|
visibly_transparent: bool,
|
||||||
|
astar_weight: u8,
|
||||||
|
visible_range: [u32; 8],
|
||||||
|
) -> Self {
|
||||||
|
let mut flags = 0u8;
|
||||||
|
if can_stand_in {
|
||||||
|
flags |= 0b001;
|
||||||
|
}
|
||||||
|
if can_stand_on {
|
||||||
|
flags |= 0b010;
|
||||||
|
}
|
||||||
|
if visibly_transparent {
|
||||||
|
flags |= 0b100;
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
flags,
|
||||||
|
astar_weight,
|
||||||
|
visible_range,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn can_stand_in(&self) -> bool {
|
||||||
|
self.flags & 0b001 != 0
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn can_stand_on(&self) -> bool {
|
||||||
|
self.flags & 0b010 != 0
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn visibly_transparent(&self) -> bool {
|
||||||
|
self.flags & 0b100 != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_can_stand_in(&mut self, value: bool) {
|
||||||
|
if value {
|
||||||
|
self.flags |= 0b001;
|
||||||
|
} else {
|
||||||
|
self.flags &= !0b001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_can_stand_on(&mut self, value: bool) {
|
||||||
|
if value {
|
||||||
|
self.flags |= 0b010;
|
||||||
|
} else {
|
||||||
|
self.flags &= !0b010;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_visibly_transparent(&mut self, value: bool) {
|
||||||
|
if value {
|
||||||
|
self.flags |= 0b100;
|
||||||
|
} else {
|
||||||
|
self.flags &= !0b100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_tuple(tuple: (i32, bool, bool, bool, i32, [u32; 8])) -> Self {
|
||||||
|
Self::new(
|
||||||
|
tuple.0 as u8,
|
||||||
|
tuple.1,
|
||||||
|
tuple.2,
|
||||||
|
tuple.3,
|
||||||
|
tuple.4 as u8,
|
||||||
|
tuple.5,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_tuple(&self) -> (i32, bool, bool, bool, i32, [u32; 8]) {
|
||||||
|
(
|
||||||
|
self.id as i32,
|
||||||
|
self.can_stand_in(),
|
||||||
|
self.can_stand_on(),
|
||||||
|
self.visibly_transparent(),
|
||||||
|
self.astar_weight as i32,
|
||||||
|
self.visible_range,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Packed fixture tile data. ~18 bytes vs 48 bytes tuple.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct FixtureTileData {
|
||||||
|
pub id: u8,
|
||||||
|
/// bit0=can_stand_in, bit1=can_stand_on
|
||||||
|
pub flags: u8,
|
||||||
|
pub visible_range: [u32; 8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FixtureTileData {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
id: 0,
|
||||||
|
flags: 0,
|
||||||
|
visible_range: [0; 8],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FixtureTileData {
|
||||||
|
pub fn new(id: u8, can_stand_in: bool, can_stand_on: bool, visible_range: [u32; 8]) -> Self {
|
||||||
|
let mut flags = 0u8;
|
||||||
|
if can_stand_in {
|
||||||
|
flags |= 0b001;
|
||||||
|
}
|
||||||
|
if can_stand_on {
|
||||||
|
flags |= 0b010;
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
flags,
|
||||||
|
visible_range,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn can_stand_in(&self) -> bool {
|
||||||
|
self.flags & 0b001 != 0
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn can_stand_on(&self) -> bool {
|
||||||
|
self.flags & 0b010 != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_tuple(tuple: (i32, bool, bool, [u32; 8])) -> Self {
|
||||||
|
Self::new(tuple.0 as u8, tuple.1, tuple.2, tuple.3)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_tuple(&self) -> (i32, bool, bool, [u32; 8]) {
|
||||||
|
(
|
||||||
|
self.id as i32,
|
||||||
|
self.can_stand_in(),
|
||||||
|
self.can_stand_on(),
|
||||||
|
self.visible_range,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tile map with fast AHashMap for pathfinding lookups.
|
||||||
|
#[derive(Resource, Default)]
|
||||||
pub struct TileMap {
|
pub struct TileMap {
|
||||||
pub floor_tiles: HashMap<IVec3, (i32, bool, bool, bool, i32, [u32; 8])>, //id, canStandIn, canStandOn, visiblyTransparent, astar_weight, visible_range
|
pub floor_tiles: AHashMap<IVec3, FloorTileData>,
|
||||||
pub fixture_tiles: HashMap<IVec3, (i32, bool, bool, [u32; 8])>, // id, canStandIn, canStandOn, visible_range
|
pub fixture_tiles: AHashMap<IVec3, FixtureTileData>,
|
||||||
pub item_tiles: HashMap<IVec3, Vec<u32>>, // Entity.id's of items on this tile
|
pub item_tiles: AHashMap<IVec3, Vec<u32>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TileMap {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_floor(&self, pos: &IVec3) -> Option<&FloorTileData> {
|
||||||
|
self.floor_tiles.get(pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_fixture(&self, pos: &IVec3) -> Option<&FixtureTileData> {
|
||||||
|
self.fixture_tiles.get(pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn has_floor(&self, pos: &IVec3) -> bool {
|
||||||
|
self.floor_tiles.contains_key(pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn has_fixture(&self, pos: &IVec3) -> bool {
|
||||||
|
self.fixture_tiles.contains_key(pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ pub fn handle_tile_occlusion_updates(
|
|||||||
if let Some(visibility) = update_map.get(&pos.translation.as_ivec3()) {
|
if let Some(visibility) = update_map.get(&pos.translation.as_ivec3()) {
|
||||||
tile.visible_range = *visibility;
|
tile.visible_range = *visibility;
|
||||||
if let Some(tile_data) = tilemap.floor_tiles.get_mut(&pos.translation.as_ivec3()) {
|
if let Some(tile_data) = tilemap.floor_tiles.get_mut(&pos.translation.as_ivec3()) {
|
||||||
tile_data.5 = *visibility;
|
tile_data.visible_range = *visibility;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ pub fn calculate_visibility(pos: IVec3, tilemap: &TileMap) -> [u32; 8] {
|
|||||||
pos.z + z_offset * ITILE_SIZE,
|
pos.z + z_offset * ITILE_SIZE,
|
||||||
);
|
);
|
||||||
match tilemap.floor_tiles.get(&neighbor_pos) {
|
match tilemap.floor_tiles.get(&neighbor_pos) {
|
||||||
Some(&(id, _, _, _, _, _)) if id == 0 => break 'neighbor_check true,
|
Some(tile) if tile.id == 0 => break 'neighbor_check true,
|
||||||
None => {}
|
None => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -163,8 +163,8 @@ pub fn calculate_visibility(pos: IVec3, tilemap: &TileMap) -> [u32; 8] {
|
|||||||
let camera_z_index = (check_pos.z / ITILE_SIZE) + z_below;
|
let camera_z_index = (check_pos.z / ITILE_SIZE) + z_below;
|
||||||
|
|
||||||
if camera_z_index < 0 {
|
if camera_z_index < 0 {
|
||||||
if let Some(&(_, _, _, vt, _, _)) = tilemap.floor_tiles.get(&check_pos) {
|
if let Some(tile) = tilemap.floor_tiles.get(&check_pos) {
|
||||||
occluded = !vt;
|
occluded = !tile.visibly_transparent();
|
||||||
} else {
|
} else {
|
||||||
occluded = false;
|
occluded = false;
|
||||||
}
|
}
|
||||||
@@ -180,8 +180,8 @@ pub fn calculate_visibility(pos: IVec3, tilemap: &TileMap) -> [u32; 8] {
|
|||||||
visible_range[z2 / 32] |= 1 << (z2 % 32);
|
visible_range[z2 / 32] |= 1 << (z2 % 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(&(_, _, _, vt, _, _)) = tilemap.floor_tiles.get(&check_pos) {
|
if let Some(tile) = tilemap.floor_tiles.get(&check_pos) {
|
||||||
occluded = !vt;
|
occluded = !tile.visibly_transparent();
|
||||||
} else {
|
} else {
|
||||||
occluded = false;
|
occluded = false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user