From d19048c4a8fb9b7505ad8bf329643fd2e34f2728 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Wed, 20 Jul 2022 10:12:14 -0500 Subject: [PATCH] Use AABB intersection rather than point containment. --- src/visibility.rs | 100 ++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 38 deletions(-) diff --git a/src/visibility.rs b/src/visibility.rs index 47a73ef..bdd7403 100644 --- a/src/visibility.rs +++ b/src/visibility.rs @@ -6,7 +6,10 @@ use std::{ use bevy::prelude::*; -use bevy_rapier2d::na::{Isometry2, Point2, Vector2}; +use bevy_rapier2d::{ + na::{Isometry2, Vector2}, + parry::bounding_volume::BoundingVolume, +}; use coord_2d::{Coord, Size}; use shadowcast::{vision_distance, Context, InputGrid}; @@ -21,10 +24,6 @@ use crate::{ #[reflect(Component)] pub struct DontLogWhenVisible; -#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect)] -#[reflect(Component)] -struct LastCoordinates((i32, i32)); - #[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect)] #[reflect(Component)] pub struct RevealedTiles(pub Vec); @@ -75,7 +74,11 @@ impl Viewshed { Vector2::new(transform.translation.x, transform.translation.y), 0., ); - // println!("Pushing {:?}", collider.raw.compute_aabb(&position)); + // println!( + // "Hit {:?}, pushing {:?}", + // entity, + // collider.raw.compute_aabb(&position) + // ); boxes.push(collider.raw.compute_aabb(&position)); } true @@ -95,38 +98,53 @@ impl Viewshed { // println!("Out of range"); return u8::MAX; } - let point = Point2::new(shape_pos.x, shape_pos.y); - let mut hit = false; - for b in &boxes { - if b.contains_local_point(&point) { - // println!("Hit at {:?}", b); - hit = true; - break; + let result = if let Some((opacity, coord_entities)) = cache.get(&(coord.x, coord.y)) + { + Some((*opacity, coord_entities.clone())) + } else { + let position = Isometry2::new(Vector2::new(shape_pos.x, shape_pos.y), 0.); + let aabb = shape.raw.compute_aabb(&position); + let mut hit = false; + for b in &boxes { + if b.intersects(&aabb) { + // println!("Hit at {:?}", b); + hit = true; + break; + } } - } - if hit { - // println!("Hit test"); - let mut opacity = 0; - let mut coord_entities = HashSet::new(); - rapier_context.intersections_with_shape( - shape_pos, - 0., - &shape, - QueryFilter::new().predicate(&|v| visible_query.get(v).is_ok()), - |entity| { - // println!("{:?}", entity); - let obstruction = obstructions_query.get(entity).is_ok(); - if obstruction { - // println!("Obstruction"); - coord_entities.clear(); - } - coord_entities.insert(entity); - if let Ok((visible, _, _)) = visible_query.get(entity) { - opacity = opacity.max(**visible); - } - !obstruction - }, - ); + if hit { + // println!("Hit test"); + let mut opacity = 0; + let mut coord_entities = HashSet::new(); + rapier_context.intersections_with_shape( + shape_pos, + 0., + &shape, + QueryFilter::new().predicate(&|v| visible_query.get(v).is_ok()), + |entity| { + // println!("{:?}", entity); + let obstruction = obstructions_query.get(entity).is_ok(); + if obstruction { + // println!("Obstruction"); + coord_entities.clear(); + } + coord_entities.insert(entity); + if let Ok((visible, _, _)) = visible_query.get(entity) { + opacity = opacity.max(**visible); + } + !obstruction + }, + ); + cache.insert((coord.x, coord.y), (opacity, coord_entities.clone())); + Some((opacity, coord_entities)) + } else { + // println!("No hits, 0"); + let coord_entities = HashSet::new(); + cache.insert((coord.x, coord.y), (0, coord_entities.clone())); + Some((0, coord_entities)) + } + }; + if let Some((opacity, coord_entities)) = result { for e in &coord_entities { new_visible_entities.insert(*e); } @@ -138,7 +156,6 @@ impl Viewshed { opacity } } else { - // println!("No hits, 0"); 0 } })), @@ -159,12 +176,19 @@ impl Viewshed { } if new_visible_entities != **visible_entities { for lost in visible_entities.difference(&new_visible_entities) { + if let Ok((_, _, transform)) = visible_query.get(*lost) { + // println!( + // "transition: {:?} loses {:?} at {:?}", + // viewer_entity, lost, transform.translation + // ); + } events.send(VisibilityChanged::Lost { viewer: *viewer_entity, viewed: *lost, }); } for gained in new_visible_entities.difference(visible_entities) { + // println!("transition: {:?} gains {:?}", viewer_entity, gained); events.send(VisibilityChanged::Gained { viewer: *viewer_entity, viewed: *gained,