Major visibility system updates.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Nolan Darilek 2022-05-17 10:37:46 -05:00
parent 64fd169ba2
commit 615af720cb

View File

@ -73,13 +73,20 @@ impl Viewshed {
map, map,
RefCell::new(Box::new(|coord: Coord| { RefCell::new(Box::new(|coord: Coord| {
let dest = Point2::new(coord.x as f32 + 0.5, coord.y as f32 + 0.5); let dest = Point2::new(coord.x as f32 + 0.5, coord.y as f32 + 0.5);
if na::distance(&origin, &dest) > self.range as f32 {
return u8::MAX;
}
if let Some((opacity, entities)) = cache.get(&(FloatOrd(dest.x), FloatOrd(dest.y))) if let Some((opacity, entities)) = cache.get(&(FloatOrd(dest.x), FloatOrd(dest.y)))
{ {
for e in entities { for e in entities {
new_visible_entities.insert(*e); new_visible_entities.insert(*e);
} }
if entities.contains(&viewer_entity) {
return 0;
} else {
return *opacity; return *opacity;
} }
}
let tile = map.at(coord.x as usize, coord.y as usize); let tile = map.at(coord.x as usize, coord.y as usize);
if tile.blocks_visibility() { if tile.blocks_visibility() {
cache.insert( cache.insert(
@ -88,34 +95,32 @@ impl Viewshed {
); );
return u8::MAX; return u8::MAX;
} }
if na::distance(&origin, &dest) > self.range as f32 {
return u8::MAX;
}
let mut opacity = 0; let mut opacity = 0;
let mut entities = HashSet::new(); let mut entities = HashSet::new();
let shape_pos = Vec2::new(coord.x as f32 + 0.5, coord.y as f32 + 0.5); let shape_pos = Vec2::new(dest.x, dest.y);
rapier_context.intersections_with_shape( rapier_context.intersections_with_shape(
shape_pos, shape_pos,
0., 0.,
&shape, &shape,
InteractionGroups::all(), InteractionGroups::all(),
Some(&|v| v != *viewer_entity && visible_query.get(v).is_ok()), Some(&|v| visible_query.get(v).is_ok()),
|entity| { |entity| {
entities.insert(entity); entities.insert(entity);
if let Ok(visible) = visible_query.get(entity) { if let Ok(visible) = visible_query.get(entity) {
opacity = **visible; opacity = opacity.max(**visible);
} }
cache.insert(
(FloatOrd(dest.x), FloatOrd(dest.y)),
(opacity, entities.clone()),
);
true true
}, },
); );
for e in &entities { for e in &entities {
new_visible_entities.insert(*e); new_visible_entities.insert(*e);
} }
if entities.contains(&viewer_entity) {
0
} else {
cache.insert((FloatOrd(dest.x), FloatOrd(dest.y)), (opacity, entities));
opacity opacity
}
})), })),
); );
let mut new_visible = HashSet::new(); let mut new_visible = HashSet::new();
@ -259,15 +264,12 @@ where
fn update_viewshed<D: 'static + Clone + Default + Send + Sync>( fn update_viewshed<D: 'static + Clone + Default + Send + Sync>(
mut commands: Commands, mut commands: Commands,
config: Res<RapierConfiguration>, config: Res<RapierConfiguration>,
positions: Query<(Entity, &Transform, Option<&LastCoordinates>), Changed<Transform>>, positions: Query<
(Entity, &Transform, &Collider, Option<&LastCoordinates>),
Or<(Changed<Transform>, Changed<Visible>)>,
>,
visible: Query<&Visible>, visible: Query<&Visible>,
mut viewers: Query<( mut viewers: Query<(Entity, &mut Viewshed, &mut VisibleEntities, &Transform)>,
Entity,
&mut Viewshed,
&mut VisibleEntities,
&Transform,
Option<&LastCoordinates>,
)>,
map: Query<&Map<D>>, map: Query<&Map<D>>,
rapier_context: Res<RapierContext>, rapier_context: Res<RapierContext>,
mut changed: EventWriter<VisibilityChanged>, mut changed: EventWriter<VisibilityChanged>,
@ -276,7 +278,7 @@ fn update_viewshed<D: 'static + Clone + Default + Send + Sync>(
return; return;
} }
let mut to_update = HashSet::new(); let mut to_update = HashSet::new();
for (entity, transform, last_coordinates) in positions.iter() { for (entity, transform, collider, last_coordinates) in positions.iter() {
if to_update.contains(&entity) { if to_update.contains(&entity) {
continue; continue;
} }
@ -297,34 +299,26 @@ fn update_viewshed<D: 'static + Clone + Default + Send + Sync>(
if visible.get(entity).is_err() { if visible.get(entity).is_err() {
continue; continue;
} }
for ( for (viewer_entity, viewshed, visible_entities, viewer_coordinates) in viewers.iter_mut() {
viewer_entity, if viewer_entity != entity {
viewshed, let forward = transform.local_x();
visible_entities, let rotation = forward.y.atan2(forward.x);
viewer_coordinates, let distance = collider.distance_to_point(
viewer_last_coordinates, transform.translation.truncate(),
) in viewers.iter_mut() rotation,
{ viewer_coordinates.translation.truncate(),
if let (Some(last_coordinates), Some(viewer_last_coordinates)) = true,
(last_coordinates, viewer_last_coordinates) );
{ if distance <= viewshed.range as f32 || visible_entities.contains(&entity) {
if viewer_coordinates.i32() == **viewer_last_coordinates
&& coordinates.i32() == **last_coordinates
{
continue;
}
}
if viewer_entity != entity
&& (viewer_coordinates.distance(&coordinates) <= viewshed.range as f32
|| visible_entities.contains(&entity))
{
to_update.insert(viewer_entity); to_update.insert(viewer_entity);
to_update.insert(entity);
}
} }
} }
} }
let mut cache = HashMap::new(); let mut cache = HashMap::new();
for entity in to_update.iter() { for entity in to_update.iter() {
if let Ok((viewer_entity, mut viewshed, mut visible_entities, viewer_coordinates, _)) = if let Ok((viewer_entity, mut viewshed, mut visible_entities, viewer_coordinates)) =
viewers.get_mut(*entity) viewers.get_mut(*entity)
{ {
if let Ok(map) = map.get_single() { if let Ok(map) = map.get_single() {